14

为什么我应该将 #' 与 lambda 一起使用?它通常是这样写的,所以我想这是一种很好的形式。但这些线似乎和我一样:

> (mapcar #'(lambda (x) (+ x 1)) '(1 2 3))
(2 3 4)
> (mapcar (lambda (x) (+ x 1)) '(1 2 3))
(2 3 4)

有人愿意让初学者了解差异吗?

4

2 回答 2

14

在各种 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) 的形式。

于 2009-05-26T07:01:30.527 回答
11

#'是 的简写function,它返回一个指向函数的指针(而不是应用它)。 lambda返回一个函数,通常需要一个指向该函数的指针。由于这很常见,因此还有一个宏(在变量空间中)可以为您执行此操作,它也被调用lambda。两行代码是相同的。

哪个更好归结为Lisp-1/Lisp-2 辩论:在 Common Lisp 中,由于宏,您可以做任何一个。一如既往,保持一致。

于 2009-05-26T00:45:11.477 回答