为什么在Emacs Lisp中的函数参数前要使用#'符号?

19

我熟悉Emacs Lisp,但不是Common Lisp(或其他任何)Lisp。一些Lisp程序员建议(例如Emacs的基本函数),在Lisp代码中在函数参数前使用#'是很好的。例如:

(mapc #'my-fun '(1 2 3))
在Emacs Lisp中,我相信这等同于

(mapc 'my-fun '(1 2 3))

从elisp手册第12.7节中得知。

读取语法#'是使用function的一种简写方式。以下形式都是等价的:

 (lambda (x) (* x x))
 (function (lambda (x) (* x x)))
 #'(lambda (x) (* x x))

并且帮助function函数

function是在eval.c中的一个特殊形式。

(function ARG)

quote类似,但更适用于函数对象。在字节编译中,function使其参数被编译。而quote则不能实现此功能。

所以这似乎是一个潜在的优化,但也不过如此。此外,来自ML/Haskell背景的人会觉得将函数与任何其他数据区别对待很奇怪。

问题:

你是否认为应该在emacs-lisp函数参数中使用#'?(简要说明为什么它们在Common Lisp中需要也很好)

注:

我原以为当省略#'时会读取不同的单元格(值与函数),但这似乎是错误的,因为function的文档没有提到获取函数单元格。可以使用symbol-function来实现。相关问题如下:

但它们似乎表明在Lambda中至少不需要#'


2
可能是Emacs #'function语法应该在什么时候使用?的重复问题。 - phils
ELCL都是LISP2的一部分。也就是说,它们在函数和变量方面具有不同的命名空间。并非所有的LISPs都是这样的,例如,Scheme只有一个命名空间,因此根本不需要funcall。例如:(let ((x (lambda (y) (+ y y)))) (x 5)) - Sylwester
感谢您进行的所有编辑。 - seanmcl
1个回答

22
#'foo 中的引号与 'foo 中的引号无关。 #'foo读取时间 被替换为 (function foo)。编译并执行时,它会查找由 defunfletlabels 或类似语句定义的名为 foo函数定义'foo读取时间 被替换为 (quote foo)。编译并执行时,它仅仅被替换为符号 fooFuncallapply(因此通常也是高阶函数)以 函数指示器 作为参数。 函数指示器 可以是一个函数,也可以是命名函数的符号,因此 #'foo'foo 都是函数指示器。
因此,'foo#'foo 形式乍一看似乎可以互换。但是,真实函数的查找在不同的时间进行 - 查找 #'foo 发生在调用它的地方,而命名为 'foo 的函数只有在最终应用时才会被查找。
如果您多次使用函数指示器,则在读取时间、甚至只在编译时间进行一次查找要更有效率。这可以节省很多时间,并且在编辑器中可以提供更流畅的用户体验。

4
еңЁEmacs LispдёӯпјҢжҲ‘зЎ®е®һи®Өдёә'fooе’Ң#'fooжҳҜзӯүд»·зҡ„пјҢдҪҶдҪҝз”ЁеҗҺиҖ…д»Қ然表жҳҺдҪ жӯЈеңЁеҜ»жүҫдёҖдёӘеҮҪж•°е®ҡд№үгҖӮ - Vatine
你想在绑定中使用 #'function 来调用内置函数,比如 (global-set-key (kbd "C-c s") 'save-buffer) 吗?或者在绑定中调用 fset 宏定义呢? - young_souvlaki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接