[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 433b6fc: Handle single-argument `apply' consistently (bug#40968)
From: |
Lars Ingebrigtsen |
Subject: |
master 433b6fc: Handle single-argument `apply' consistently (bug#40968) |
Date: |
Sun, 27 Sep 2020 11:02:37 -0400 (EDT) |
branch: master
commit 433b6fc53dc9511077ed3a8c1ad130196dedbb55
Author: Pip Cet <pipcet@gmail.com>
Commit: Lars Ingebrigtsen <larsi@gnus.org>
Handle single-argument `apply' consistently (bug#40968)
* src/eval.c (Fapply): Handle (apply nil) without crashing.
Document single-argument form.
* lisp/emacs-lisp/byte-opt.el (byte-optimize-apply): Don't attempt
to optimize single-argument apply.
* doc/lispref/functions.texi (Calling Functions): Document
single-argument apply. Provide example (bug#40968).
---
doc/lispref/functions.texi | 10 ++++++++++
lisp/emacs-lisp/byte-opt.el | 29 ++++++++++++++++-------------
src/eval.c | 6 ++++++
3 files changed, 32 insertions(+), 13 deletions(-)
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index 26b212d..e8e2207 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -762,6 +762,11 @@ arguments, rather than a single list. We say that
@code{apply}
@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. Passing two or
+more arguments will be faster.
+
@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
@@ -789,6 +794,11 @@ primitive function; special forms and macros do not make
sense in
(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 8a6c0b9..65e4e44 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1044,19 +1044,22 @@
(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 not worth optimizing (bug#40968)
+ 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 5d3c323..c34c118 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2371,6 +2371,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)
@@ -2381,6 +2383,10 @@ usage: (apply FUNCTION &rest ARGUMENTS) */)
Lisp_Object fun = args[0];
USE_SAFE_ALLOCA;
+ if (nargs == 1)
+ /* Special case: FUN is really a list of (FUNCTION . ARGS). */
+ return CALLN (Fapply, CAR (fun), CDR (fun));
+
ptrdiff_t numargs = list_length (spread_arg);
if (numargs == 0)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master 433b6fc: Handle single-argument `apply' consistently (bug#40968),
Lars Ingebrigtsen <=