基本上,我什么时候应该使用Emacs Lisp的function
程序?如果您将函数作为参数'like-this
或#'like-this
传递,我没有找到任何行为存在差异的示例。事实上,如果我评估(eq 'goto-char #'goto-char)
,则会返回t
。
我遇到的Emacs Lisp代码很少使用function
/ #'
;作者只是quote
/ '
一切
示例:(add-hook 'emacs-lisp-hook 'turn-on-eldoc-mode)
但是,我可以找到一些反例。这是Emacs 24.3 electric.el
的源代码中的一个:
(add-hook 'post-self-insert-hook
#'electric-indent-post-self-insert-function
'append)
(do-something '(lambda …
(do-something (lambda …
'
和#'
之间的差异?答案 0 :(得分:30)
function
(又名#'
)用于引用函数,而quote
(又名'
)用于引用数据。现在,在Emacs-Lisp中,一个函数单元是函数的符号本身就是一个函数,所以#'symbol
在实践中与'symbol
相同(意图不同,第一个明确表示一个不只是谈论符号“符号”而是关于名为“符号”的函数。
差异不仅仅是风格的地方是引用lambdas:'(lambda ...)
是一个表达式,它计算为 list ,其第一个元素是符号lambda
。您可以将car
和cdr
等内容应用于此,但您不应将其称为功能(尽管实际上它可以正常工作)。相反,#'(lambda ...)
(可以只写(lambda ...)
)是一个表达式,它计算为函数。这意味着您不能将car
应用于它,但字节编译器可以查看#'(lambda ...)
内部,在其中执行宏扩展,警告您,如果它找到的内容看起来不是犹太洁食,等等。 ..;对于词法绑定,即使必须查看内部,以便找到该函数所引用的自由变量。
答案 1 :(得分:12)
在elisp #'
中(实际上)纯粹是关于字节编译(编辑:因为Emacs 24,也是词汇闭包);但你也可能永远不需要使用它。
#'...
是(function ...)
的简写,它只是'...
/ (quote ...)
的变体,它还向字节编译器提示它可以编译引用的表单作为一种功能。
然而,在现代Emacs中(IIRC并非总是这样),(lambda ...)
相当于#'(lambda ...)
,所以我相信你很少(如果有的话)需要写#'
。
你也很少想要使用'(lambda ...)
,因为Stefan已经详细阐述了原因(但是'symbol
很好)。
这在 Ch i g (elisp) Anonymous Functions
RET 的手册中有所介绍(尽管有似乎是最后一段示例代码中的错误,因为它与前面的示例相同(在Emacs 24.3.1中)。
(n.b.Stefan的答案是肯定的,但是我会把它保留在这里,因为它有希望补充它。)
答案 2 :(得分:5)
除了引用(lambda ...)
表单时的差异,最近(从Emacs 24.4开始)对 bytecomp.el 进行了更改,以便在{{1}时生成警告使用了form,但不知道在编译结束时定义的函数。
使用函数引用#'symbol
语法而不是#'symbol
语法编写所有函数符号因此有些优先,因为它允许字节编译器检查您是否使用了实际的函数名称定义
以前(Emacs 24.3及更早版本),而字节编译器会在您将函数调用为'symbol
并且未定义或从其他文件中干净地导入时发出警告,类似(no-such-function ...)
之类的内容只产生运行时错误而没有编译时警告。
这一变化意味着这两种情况现在都会产生编译时警告;但是,如果您使用(mapcar #'no-such-function ...)
而不使用使用函数引用,那么再次,不会生成编译时警告。因此(mapcar 'no-such-function ...)
可以帮助您尽早发现错误(可能是错别字)。
函数引用也有助于自上而下的编程风格,因为字节编译器将列出您尚未实现的函数(但会遗漏用正常引用指定的函数)。