The Emacs code for apply-partially
is this:
(defun apply-partially (fun &rest args)
"Return a function that is a partial application of FUN to ARGS.
ARGS is a list of the first N arguments to pass to FUN.
The result is a new function which does the same as FUN, except that
the first N arguments are fixed at the values with which this function
was called."
`(closure (t) (&rest args)
(apply ',fun ,@(mapcar (lambda (arg) `',arg) args) args)))
It returns a list that looks a lot like a lambda expression, except that lambda
is replaced by closure (t)
. For example, (apply-partially 'cons 1)
returns this:
(closure (t) (&rest args) (apply (quote cons) (quote 1) args))
which, as far as I can tell, looks and works exactly like this:
(lambda (&rest args) (apply (quote cons) (quote 1) args))
except that the "closure" expression does not have the "self-quoting" property of a lambda, so when I try to evaluate it, Emacs informs me that closure
has no function definition: Lisp error: (void-function closure)
.
I can't find any references in the Elisp manual to using the symbol closure
in this way. It seems like some kind of internal Emacs magic. The closure expression is clearly not being evaluated according to the normal rules (since doing that manually gives an error).
So what's going on here? Do I need to grep the C code for references to "closure" to find out?
EDIT: It appears that in Emacs 23 and below, apply-partially
simply uses the lexical-let
from the cl package to make a closure. The definition above is from version "24.0.90.1".
I found the answer in eval.c
, in the funcall_lambda
function:
if (EQ (XCAR (fun), Qclosure))
{
fun = XCDR (fun); /* Drop `closure'. */
lexenv = XCAR (fun);
CHECK_LIST_CONS (fun, fun);
}
else
lexenv = Qnil;
closure (t)
appears to be the lexical equivalent of lambda
. The second element, (t)
, gets assigned to lexenv
, so I guess this element is for closing over lexical values defined outside of the function itself or something.
I suspect that the lack of self-quoting may be an oversight, which can be remedied as follows:
(defmacro make-self-quoting (name)
"Make NAME into a self-quoting function like `lambda'."
`(defmacro ,name (&rest cdr)
(list 'function (cons ',name cdr))))
(make-self-quoting closure)
With my "GNU Emacs 23.2.1 (i686-pc-cygwin)" it is defined as
(defun apply-partially (fun &rest args)
"Return a function that is a partial application of FUN to ARGS.
ARGS is a list of the first N arguments to pass to FUN.
The result is a new function which does the same as FUN, except that
the first N arguments are fixed at the values with which this function
was called."
(lexical-let ((fun fun) (args1 args))
(lambda (&rest args2) (apply fun (append args1 args2)))))
Understanding how it works seems to be quite easy here: The lambda
remembers the partial set of args and appends the rest when calling the original function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With