如何使用“部分应用”?

Rob*_*mba 3 emacs elisp

我正在尝试在本地上下文中使用 apply-partially:

((apply-partially '+ 1) `(1))
Run Code Online (Sandbox Code Playgroud)

这给我以下错误:eval: Invalid function: (apply-partially (quote +) 1)

相似地:

(let ((addone (apply-partially #'+ 1)))
  (addone 2))
Run Code Online (Sandbox Code Playgroud)

为什么这个例子中的任何一个都不起作用?

leg*_*cia 7

这是因为 Emacs Lisp 对于变量和函数有单独的命名空间。可以通过将其名称放在列表中的第一位并对其求值来调用已使用定义的函数defun,但如果您有一个函数作为值(由 所返回apply-partially),则需要使用funcallapply

funcall和之间的区别apply在于,funcall仅使用给定的参数调用函数,而apply将其最后一个参数视为应附加到参数列表的列表。因此,您的第一个示例需要使用 编写apply,因为+不适用于列表:

(apply (apply-partially '+ 1) `(1))
Run Code Online (Sandbox Code Playgroud)

对于第二个示例,请使用funcall,因为函数参数未包装在列表中:

(let ((addone (apply-partially #'+ 1)))
  (funcall addone 2))
Run Code Online (Sandbox Code Playgroud)

这有时被称为“Lisp-1”与“Lisp-2”。“Lisp-1”语言(例如Scheme 和 Clojure)具有一个用于变量和函数的命名空间,而“Lisp-2”语言(例如 Emacs Lisp 和 Common Lisp)则具有单独的命名空间。也可以看看:

它在 Emacs Lisp 中的工作方式是每个符号都有多个“单元”,一个用于其作为变量的值,另一个用于其函数定义。因此,符号的函数单元格list包含内置函数,而您可以自由地将任何您想要的值放入其value单元格中。(这不适用于词法变量,词法变量存储在“词法环境”中而不是符号的值单元格中。)

事实上,每个符号都有第三个单元格保存其属性列表。get您可以使用和函数访问符号的各个属性put,并且可以通过调用 来获取整个正确列表symbol-plist。所以你可以说 Emacs Lisp 有超过 2 个命名空间,尽管它被称为“Lisp-2”语言。