Lisp中'和#'有什么区别?

时间:2011-02-05 10:09:43

标签: lisp quote

似乎都是

(mapcar 'car '((foo bar) (foo1 bar1))) 

(mapcar #'car '((foo bar) (foo1 bar1)))

同样的工作。

我也知道'表示(引用符号),#'表示(函数函数名称)。

但潜在的差异是什么?为什么这两个都适用于之前的mapcar

3 个答案:

答案 0 :(得分:14)

'foo

评估符号FOO。

#'foo

计算绑定到名称FOO的函数。

在Lisp中,当符号FOO具有功能绑定时,可以将符号称为函数。 CAR是一个具有功能绑定的符号。

但这不起作用:

(flet ((foo (a) (+ a 42)))
  (mapcar 'foo '(1 2 3 4 5)))

那是因为作为符号的FOO不能访问本地词法函数,并且当foo不是其他地方定义的函数时,Lisp系统会抱怨。

我们需要写:

(flet ((foo (a) (+ a 42)))
  (mapcar #'foo '(1 2 3 4 5)))

这里(函数foo)或它的简写符号''foo引用词法局部函数FOO。

另请注意

(funcall #'foo ...)

VS

(funcall 'foo ...)

后者可能会再做一次间接,因为它需要从符号中查找函数,而#'foo直接表示函数。

<强>摘要

如果符号具有功能绑定,则通过符号调用函数。

答案 1 :(得分:9)

  

为什么这两个都在以前的mapcar中工作?

mapcar的文档说:

  

如果函数是一个符号,它就像强制symbol-function一样被强制转换为函数。

答案 2 :(得分:2)

尝试将匿名函数(lambda)传递给mapcar,您将看到#'是必需的,因为引用本身需要一个绑定到函数的符号,但符号不是存在于未命名的函数中:

CL-USER> (mapcar '(lambda (x) (format t "it is ~d" x)) (list 3 5 7))
; Evaluation aborted on #<TYPE-ERROR expected-type: (OR FUNCTION SYMBOL)
             datum: (LAMBDA (X) (FORMAT T "it is ~d" X))>.

VS

CL-USER> (mapcar #'(lambda (x) (format t "it is ~d" x)) (list 3 5 7))
it is 3it is 5it is 7
(NIL NIL NIL)