什么时候应该使用Emacs#'函数语法?

时间:2013-05-28 20:58:47

标签: emacs lisp elisp

基本上,我什么时候应该使用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)

猜测和进一步的问题:

  • 它只是一个Lisp-2风格约定吗?
  • 是否与字节编译有关?
  • 这对图书馆作家有用吗?比如,如果您希望您的代码在大量环境和Emacs版本下运行? (推论如果你只是“dotfile-tinkering”那么你就不用担心这一切了。)
  • 我什么时候应该引用lambda表达式?我什么时候可以不加引号?
    例如,(do-something '(lambda …
    (do-something (lambda …
  • 早期版本的Emacs是否存在某些限制,这些限制引发了elisp的这些方面?比如,只要我使用比 X 更新的Emacs版本,我是否可以忽略'#'之间的差异?

3 个答案:

答案 0 :(得分:30)

function(又名#')用于引用函数,而quote(又名')用于引用数据。现在,在Emacs-Lisp中,一个函数单元是函数的符号本身就是一个函数,所以#'symbol在实践中与'symbol相同(意图不同,第一个明确表示一个不只是谈论符号“符号”而是关于名为“符号”的函数。

差异不仅仅是风格的地方是引用lambdas:'(lambda ...)是一个表达式,它计算为 list ,其第一个元素是符号lambda。您可以将carcdr等内容应用于此,但您不应将其称为功能(尽管实际上它可以正常工作)。相反,#'(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 ...)可以帮助您尽早发现错误(可能是错别字)。

函数引用也有助于自上而下的编程风格,因为字节编译器将列出您尚未实现的函数(但会遗漏用正常引用指定的函数)。