From: Pip Cet <pipcet@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: Stefan Kangas <stefan@marxist.se>, 40968@debbugs.gnu.org
Subject: bug#40968: 28.0.50; (apply nil)
Date: Wed, 6 May 2020 17:54:23 +0000 [thread overview]
Message-ID: <CAOqdjBc2+_mMt5sn3MvFvKq8yeQcbuu5=6pTvNbiPA3CPO1d2w@mail.gmail.com> (raw)
In-Reply-To: <83lfm5kvn4.fsf@gnu.org>
[-- Attachment #1: Type: text/plain, Size: 509 bytes --]
On Wed, May 6, 2020 at 2:04 PM Eli Zaretskii <eliz@gnu.org> wrote:
> 'apply' is a very popular function, and is used very widely. I won't
> be surprised if there were more of these usage cases that would be
> broken by such a change in the signature.
> Can we instead identify the problematic usage and signal an error?
Yes. What we also have to do is fix the documentation, and fix the
byte optimizer.
Here's a first suggestion. I'd particularly appreciate hints on better
wording for the documentation.
[-- Attachment #2: 0001-Handle-single-argument-apply-consistently-bug-40968.patch --]
[-- Type: text/x-patch, Size: 3926 bytes --]
From fa819045766f50c55f9bb588ecf7e0bef6a56d41 Mon Sep 17 00:00:00 2001
From: Pip Cet <pipcet@gmail.com>
Date: Wed, 6 May 2020 17:46:56 +0000
Subject: [PATCH] Handle single-argument `apply' consistently (bug#40968)
---
doc/lispref/functions.texi | 9 +++++++++
lisp/emacs-lisp/byte-opt.el | 29 ++++++++++++++++-------------
src/eval.c | 5 +++++
3 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index bc8ec0ef1b..054bcc169e 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -761,6 +761,10 @@ Calling Functions
@dfn{spreads} this list so that each individual element becomes an
argument.
+@code{apply} with a single argument is special: the first element of
+the argument, which must be a non-empty list, is called as a function
+with the remaining elements as individual arguments.
+
@code{apply} returns the result of calling @var{function}. As with
@code{funcall}, @var{function} must either be a Lisp function or a
primitive function; special forms and macros do not make sense in
@@ -788,6 +792,11 @@ Calling Functions
(apply 'append '((a b c) nil (x y z) nil))
@result{} (a b c x y z)
@end group
+
+@group
+(apply '(+ 3 4))
+ @result{} 7
+@end group
@end example
For an interesting example of using @code{apply}, see @ref{Definition
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 4f72251aed..32e53bb7e9 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1098,19 +1098,22 @@ byte-optimize-funcall
(defun byte-optimize-apply (form)
;; If the last arg is a literal constant, turn this into a funcall.
;; The funcall optimizer can then transform (funcall 'foo ...) -> (foo ...).
- (let ((fn (nth 1 form))
- (last (nth (1- (length form)) form))) ; I think this really is fastest
- (or (if (or (null last)
- (eq (car-safe last) 'quote))
- (if (listp (nth 1 last))
- (let ((butlast (nreverse (cdr (reverse (cdr (cdr form)))))))
- (nconc (list 'funcall fn) butlast
- (mapcar (lambda (x) (list 'quote x)) (nth 1 last))))
- (byte-compile-warn
- "last arg to apply can't be a literal atom: `%s'"
- (prin1-to-string last))
- nil))
- form)))
+ (if (= (length form) 2)
+ ;; single-argument `apply' is special (bug#40968)
+ (byte-optimize-apply `(apply #'funcall ,(cadr form)))
+ (let ((fn (nth 1 form))
+ (last (nth (1- (length form)) form))) ; I think this really is fastest
+ (or (if (or (null last)
+ (eq (car-safe last) 'quote))
+ (if (listp (nth 1 last))
+ (let ((butlast (nreverse (cdr (reverse (cdr (cdr form)))))))
+ (nconc (list 'funcall fn) butlast
+ (mapcar (lambda (x) (list 'quote x)) (nth 1 last))))
+ (byte-compile-warn
+ "last arg to apply can't be a literal atom: `%s'"
+ (prin1-to-string last))
+ nil))
+ form))))
(put 'funcall 'byte-optimizer 'byte-optimize-funcall)
(put 'apply 'byte-optimizer 'byte-optimize-apply)
diff --git a/src/eval.c b/src/eval.c
index 014905ce6d..77f54ad7b1 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2361,6 +2361,8 @@ eval_sub (Lisp_Object form)
DEFUN ("apply", Fapply, Sapply, 1, MANY, 0,
doc: /* Call FUNCTION with our remaining args, using our last arg as list of args.
Then return the value FUNCTION returns.
+With a single argument, call the argument's first element using the
+other elements as args.
Thus, (apply \\='+ 1 2 \\='(3 4)) returns 10.
usage: (apply FUNCTION &rest ARGUMENTS) */)
(ptrdiff_t nargs, Lisp_Object *args)
@@ -2373,6 +2375,9 @@ DEFUN ("apply", Fapply, Sapply, 1, MANY, 0,
ptrdiff_t numargs = list_length (spread_arg);
+ if (numargs == 0 && nargs == 1)
+ wrong_type_argument (Qconsp, spread_arg);
+
if (numargs == 0)
return Ffuncall (nargs - 1, args);
else if (numargs == 1)
--
2.26.2
next prev parent reply other threads:[~2020-05-06 17:54 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-29 18:26 bug#40968: 28.0.50; (apply nil) Pip Cet
2020-04-29 18:35 ` Pip Cet
2020-05-06 1:51 ` Stefan Kangas
2020-05-06 7:26 ` Pip Cet
2020-05-06 11:24 ` Stefan Kangas
2020-05-06 11:49 ` Pip Cet
2020-05-06 13:02 ` Stefan Kangas
2020-05-06 13:55 ` Pip Cet
2020-05-06 15:28 ` Stefan Kangas
2020-05-06 18:06 ` Pip Cet
2020-05-06 19:26 ` Drew Adams
2020-05-06 14:03 ` Eli Zaretskii
2020-05-06 17:54 ` Pip Cet [this message]
2020-05-06 18:09 ` Eli Zaretskii
2020-05-06 18:00 ` Drew Adams
2020-05-06 18:28 ` Noam Postavsky
2020-05-06 19:17 ` Drew Adams
2020-05-06 19:21 ` Pip Cet
2020-05-06 19:28 ` Drew Adams
2020-05-07 2:27 ` Eli Zaretskii
2020-05-06 17:46 ` Drew Adams
2020-05-06 20:32 ` Phil Sainty
2020-05-06 21:35 ` Drew Adams
2020-09-29 3:00 ` Stefan Monnier
2020-05-06 10:18 ` Mattias Engdegård
2020-05-06 10:45 ` Eli Zaretskii
2020-05-06 10:57 ` Andreas Schwab
2020-05-06 11:25 ` Pip Cet
2020-05-06 11:49 ` Mattias Engdegård
2020-05-06 18:42 ` Mattias Engdegård
2020-05-07 6:53 ` Pip Cet
2020-05-07 9:11 ` Mattias Engdegård
2020-05-07 11:54 ` Noam Postavsky
2020-05-07 11:58 ` Pip Cet
2020-05-07 12:20 ` Noam Postavsky
2020-05-07 13:53 ` Mattias Engdegård
2020-06-02 7:36 ` Pip Cet
2020-06-02 16:32 ` Drew Adams
2020-06-02 16:43 ` Eli Zaretskii
2020-06-02 16:36 ` Eli Zaretskii
2020-09-27 15:01 ` Lars Ingebrigtsen
2020-09-27 19:28 ` Drew Adams
[not found] <<CC40D602-5027-40A7-9BAB-1AADC9E4BDAE@acm.org>
[not found] ` <<CAOqdjBfj6AExvem5WWLfMiw4fEsY-xUUmosV+fj9CaPgWM16ag@mail.gmail.com>
[not found] ` <<ECEC9424-919F-4364-9294-381C8751921A@acm.org>
[not found] ` <<874kssm04d.fsf@gmail.com>
[not found] ` <<6ADF0807-7EBD-4054-8579-4D9AD3065D51@acm.org>
[not found] ` <<CAOqdjBdQne3RFTjg4hej40L5aeBx6vbGp6nXKx2TwPkLPf5NPw@mail.gmail.com>
[not found] ` <<fabfb1fd-4da1-4e72-90c9-333532011a48@default>
[not found] ` <<83pnahctad.fsf@gnu.org>
2020-06-02 17:10 ` Drew Adams
2020-06-02 18:41 ` Pip Cet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAOqdjBc2+_mMt5sn3MvFvKq8yeQcbuu5=6pTvNbiPA3CPO1d2w@mail.gmail.com' \
--to=pipcet@gmail.com \
--cc=40968@debbugs.gnu.org \
--cc=eliz@gnu.org \
--cc=stefan@marxist.se \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).