(功能)在Emacs中是否有任何用途?

时间:2014-08-12 23:41:22

标签: emacs lisp elisp

来自function表单的documentation

  

与`quote'类似,但对于作为函数的对象更喜欢。   在字节编译中,`function'导致其参数被编译。   “引用”不能那样做。

所以可以#'(lambda ...)来启用lambda表单的字节编译。

另一方面,as mentioned in the manual,不再需要了。

  

lambda表单有另一个作用:它通过使用function作为子例程告诉Emacs求值程序和字节编译器它的参数是一个函数。
  [...]以下表格都是等同的:

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

这使得函数在这种情况下无用。

还有其他情况,功能表格会有用吗?
在任何情况下,它的存在既不必要也不同于quote

3 个答案:

答案 0 :(得分:12)

#'(又名function)由lambda在内部使用,因为lambda被定义为将自身包裹在function中的宏。 但除此之外,你确实可以在不使用#'的情况下编写任何Elisp代码。还有另外一个细微之处,如果你写#'foo,你告诉Emacs你认为foo是一个函数的名称,所以最近版本的字节编译器会警告{{1} }不是一个已知的函数(就像他们多年来一直警告有关foo的调用一样)。

正如@Bruce指出的那样,使用(foo ...)代替#'foo也会对通过'foocl-flet本地定义的函数产生真正的影响:在这种情况下cl-labels指的是本地定义的函数,而#'foo只是引用'foo符号,它实际上与本地函数定义无关,因此可以通过解绑或绑定到另一个函数:

foo

返回

(cl-flet ((a () 1)) (list 'a (functionp 'a) #'a))

答案 1 :(得分:4)

lambda是一个宏。它必须扩展,并且每次都要扩展。像这样:

(lambda (x) x) -> (function (lambda (x) x)) ; #'(lambda (x) x)

function是一个特殊的运营商。事实上,它专门处理lambda表单,否则我们永远无法扩展lambda宏:

(lambda (x) x) ->
  (function (lambda (x) x)) ->
    (function (function (lambda (x) x))) ->
      ...

function查看其参数,如果它是lambda形式,则编译该函数。如果它的参数是一个符号,那么它将搜索与该符号相关联的编译函数。

因此,我们现在看到,function(如quote)不评估其论点。它必须具有特殊的行为,因此它是一个特殊的操作符。

答案 2 :(得分:4)

  

所以人们会#'(lambda ...)来启用字节编译   lambda form。

     

另一方面,正如手册中所提到的那样,已经不再存在了   必要的。

程序员不再需要编写(function(lambda ...))(或简写#'(lambda ...) ,因为(lambda ...)扩展为(函数(lambda ...))。其他答案已经很好地解释了。您首先引用函数文档:

  

从功能表格的文档:

     
    

quote类似,但对于作为函数的对象更喜欢。在字节中     编译,function导致其参数被编译。 quote     不能这样做。

  

因此,功能的文档没有解决

之间的区别
  • (function (lambda …))
  • (lambda …)

而不是

  • (quote (lambda …))
  • (function (lambda …))

在大多数现代Lisp(Common Lisp,Scheme等)中,表单(quote(lambda ...)),或者只是'(lambda ...))是只是一个列表,它不是可以调用的东西。例如,在SBCL中:

* (funcall '(lambda () 42))
; debugger invoked on a TYPE-ERROR in thread #<THREAD "initial thread" RUNNING {1002978E71}>:
;  The value (LAMBDA () 42) is not of type (OR FUNCTION SYMBOL).

但是,在Emacs Lisp中,你可以调用一个列表:

(funcall '(lambda () 42))
;=> 42

在询问功能是否适用于任何目的时,我们必须问“没有它我们能做什么”或“有什么替代方案?”我们无法回答“我们只会写(lambda ...)”,因为正如其他人所指出的那样,只是扩展为(函数(lambda ...))。如果我们没有功能,我们仍然可以使用引用。我们仍然可以写一个扩展为(quote(lambda ...)) lambda 宏,从而编写(funcall(lambda ...)),并且代码看起来一样。问题是,“有什么区别?”区别在于,在基于 quote 的版本中,我们传递文字列表,并且这些不能编译到函数中,因为我们仍然必须能够使用它们执行类似列表的事情(例如,他们的汽车 cdr )。 功能非常有用的地方,无论我们是自己编写,还是依赖宏来在扩展中使用它。它提供了一种编写功能对象而不是列表的方法。