为什么我应该将 #' 与 lambda 一起使用?它通常是这样写的,所以我想这是一种很好的形式。但这些线似乎和我一样:
> (mapcar #'(lambda (x) (+ x 1)) '(1 2 3))
(2 3 4)
> (mapcar (lambda (x) (+ x 1)) '(1 2 3))
(2 3 4)
有人愿意让初学者了解差异吗?
在各种 Lisp 方言中是不同的。以下使用 Common Lisp:
第一个 #' 是 (function ...) 的缩写。所以以下只是文字上的不同,但 Common Lisp 读起来是一样的:
#'(lambda (x) (* x 2))
和
(function (lambda (x) (* x 2)))
#' 是一个 readmacro,在 Lisp 系统读取 Lisp 代码时进行转换。
如果 Lisp 计算
(function (lambda (x) (* x 2)))
Lisp 系统创建一个函数对象,FUNCTION 将它作为它的值返回。
所以,每当你需要一个函数作为一个值时,你就需要这样写。当您想将函数作为值传递给另一个函数时,当您想从函数中返回它或当您想将它存储在变量中时,需要一个函数作为值。例子:
(map #'(lambda (x) (* x 2)) '(1 2 3))
(defun (y) #'(lambda (x) (* x y)))
(defparameter *twice-fn* #'(lambda (x) (* x 2)))
现在,什么是 (lambda (x) (* x 2)) ?
这是两个不同的事情,具体取决于上下文。
Lambda 表达式
可以使用 lambda 表达式代替函数名:
(function foo) and (function (lambda (x) (* x 2)))
和
(foo 17) and ((lambda (x) (* x 2)) 17)
以上两个是合法的 Common Lisp 语法。可以直接使用 lambda 表达式。
请注意,以下两种形式在 Common Lisp中是非法的:
(#'(lambda (x) (* x 2)) 17) ; illegal in Common Lisp
(function #'(lambda (x) (* x 2))) ; illegal in Common Lisp
宏
在 Common Lisp 标准化过程中,添加了一个宏 LAMBDA(它不是 Common Lisp 的第一个描述 CLtL1 的一部分)。它使编写稍微短一些的代码成为可能。例子:
(lambda (x) (* x 2))
在上述情况下,LAMBDA 是一个宏。在宏扩展期间,它将扩展为:
(function (lambda (x) (* x 2)))
请记住,在上面的 FUNCTION 形式中,内部 lambda 是 lambda 表达式的一部分,表示函数并且不会被扩展。
所以,现在上面的三个例子可以写成:
(map (lambda (x) (* x 2)) '(1 2 3))
(defun (y) (lambda (x) (* x y)))
(defparameter *twice-fn* (lambda (x) (* x 2)))
它稍微短一些,看起来不那么杂乱,看起来更类似于 Scheme 代码。对于习惯于读写 Scheme 代码的程序员来说,它看起来要好一些。
概括
a) (function (lambda (x) (* x 2))) 是编写将函数作为值返回的代码的“真实”方式。
b) #'(lambda (x) (* x 2)) 是上述的较短符号
c) (lambda (x) (* x 2)) 甚至更短,但使用宏扩展来创建 a) 的形式。
#'
是 的简写function
,它返回一个指向函数的指针(而不是应用它)。 lambda
返回一个函数,通常需要一个指向该函数的指针。由于这很常见,因此还有一个宏(在变量空间中)可以为您执行此操作,它也被调用lambda
。两行代码是相同的。
哪个更好归结为Lisp-1/Lisp-2 辩论:在 Common Lisp 中,由于宏,您可以做任何一个。一如既往,保持一致。