“部分应用”的定义在Emacs 24中如何工作?

“部分应用”的定义在Emacs 24中如何工作?,emacs,closures,elisp,Emacs,Closures,Elisp,部分应用的Emacs代码如下: (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 tha

部分应用的Emacs代码如下:

(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)))
它返回一个看起来很像lambda表达式的列表,只是
lambda
closure(t)
替换。例如,
(部分应用“cons 1)
返回以下内容:

(closure (t) (&rest args) (apply (quote cons) (quote 1) args))
据我所知,它的外观和工作原理与此完全相同:

(lambda (&rest args) (apply (quote cons) (quote 1) args))
除了“closure”表达式没有lambda的“self-quoting”属性之外,因此当我尝试对其求值时,Emacs通知我
closure
没有函数定义:
Lisp error:(void function closure)

我在Elisp手册中找不到任何关于以这种方式使用符号
closure
的参考。这看起来像是某种内部Emacs魔法。显然,闭包表达式没有按照正常规则进行求值(因为手动这样做会产生错误)

这是怎么回事?我是否需要在C代码中添加对“closure”的引用才能找到答案

编辑:在Emacs 23及以下版本中,
apply partially
似乎只是使用cl包中的
词法let
来完成一个闭包。上面的定义来自版本“24.0.90.1”。

和我的“GNU Emacs 23.2.1(i686 pc cygwin)”一起定义为

(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)))))

理解它是如何工作的似乎很容易:lambda在调用原始函数时会记住部分参数集,并附加其余的参数集

我在
eval.c
funcall\u lambda
函数中找到了答案:

  if (EQ (XCAR (fun), Qclosure))
{
  fun = XCDR (fun); /* Drop `closure'.  */
  lexenv = XCAR (fun);
  CHECK_LIST_CONS (fun, fun);
}
  else
lexenv = Qnil;
closure(t)
似乎是
lambda
的词汇等价物。第二个元素,
(t)
,被分配给
lexev
,所以我猜这个元素是用来结束函数本身或其他外部定义的词法值

我怀疑缺乏自我引用可能是一种疏忽,可以通过以下方式进行补救:

(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)

我正在运行Emacs24,它现在有自己的词法范围,不依赖cl包。我猜
closure
对Emacs24来说是新事物。如果它
closure
是一个符号,那么apropos一定有什么东西?有一个
defmacro closure
,但不清楚它是否是Emacs的一部分。不,文档中没有提到符号“closure”。它从不直接从任何elisp代码中使用,只从C代码中使用,因此在某种意义上它是Emacs内部的一部分。对,在部分应用的情况下,词法环境是空的,但仍然有一个区别:
args
参数将是词法绑定的,而使用
lambda
则是动态绑定的。这确保了名称
args
不会干扰该变量在其他地方的其他使用。至于缺少自引用,这实际上不是一个疏忽,根本不需要:
(闭包…
)不应该出现在源代码中。