搜索 emacs #'
应该能找到不少资料,比如: lisp - When should Emacs #'function syntax be used? - Stack Overflow
function
(aka #'
) is used to quote functions, whereas quote
(aka '
) is used to quote data. Now, in Emacs-Lisp a symbol whose function cell is a function is itself a function, so #'symbol
is just the same as 'symbol
in practice (tho the intention is different, the first making it clear that one is not just talking about the symbol “symbol” but about the function named “symbol”).
The place where the difference is not just stylistic is when quoting lambdas: '(lambda ...)
is an expression which evaluates to a list whose first element is the symbol lambda
. You’re allowed to apply things like car
and cdr
to it, but you should not call it as if it were a function (although in practice it tends to work just fine). On the contrary #'(lambda ...)
(which can be written just (lambda ...)
) is an expression which evaluates to a function. That means you can’t apply car
to it, but the byte-compiler can look inside #'(lambda ...)
, perform macro-expansion in it, warn you if what it finds doesn’t look kosher, etc…; For lexical-binding it even has to look inside in order to find the free variables to which that function refers.
可以看看 Evolution of Emacs Lisp 的 lambda 相关章节,我这里截取一段:
在 Lisp 方言中,匿名函数一般都是 lambda 表达式的值。下面是一个将数字加一的匿名函数:
(lambda (x) (+ x 1))
有趣的是, lambda
原本在 Emacs Lisp 不是一个关键字(与 MacLisp 不同),但匿名函数的值可以是以下形式的列表:
(lambda (..ARGS..) ..BODY..)
动态作用域的使用导致没有必要创建闭包,所以在源代码中直接使用已有 quote
机制编写匿名函数是可行的:
'(lambda (..ARGS..) ..BODY..)
对这个表达式求值会得到一个嵌套列表结构,它的首元素是符号 lambda
。当某个程序使用这样一个值调用 funcall
时, funcall
会将这个列表结构识别为一个 lambda
表达式并对其调用解释器。
这个额外的 '
字符是为了让 Lisp 实现更简单的小小代价。但字节码编译器不被允许编译这样的引用列表,除非在极少数情况下它能确定列表只会作为函数使用。因此 Emacs Lisp 在 1.4 版本中添加了 function
special form(也是从 MacLisp 导入的)来作为替代表示法:
(function (lambda (..ARGS..) ..BODY..))
在 1992 年,也就是 Emacs 19 的早期开发阶段, lambda
被作为宏加入到 Emacs Lisp 中。这个宏简单地将列表包裹在 function
中并返回:
(defmacro lambda (&rest args) (list 'function (cons 'lambda args)))
对于为什么在引入这个简单的宏上花了这么长的时间还不完全清楚,不过这可能是因为匿名函数并不经常使用,而且它们主要用于对性能要求不是很高的地方。
虽然 lambda 宏使得 (lambda ...)
在近 30 年来优于 '(lambda ...)
,但这种做法仍然可以在许多在网上发布的代码片段、用户配置文件和第三方 Emacs Lisp 包中找到,这主要归功于复制粘贴的便利,尽管它会阻止对函数体进行字节码编译。
有些相关的是,直到 1993 年 Lucid Emacs 19.8 才从 MacLisp 中引入了 '#...
作为 (function ...)
的读取器简写形式。Emacs 则在随后的一年跟进。