为什么要引用lambda表达式?
这是在通用Lisp上的On Lisp中经常使用的一种技术:为什么要引用lambda表达式?,lambda,lisp,elisp,common-lisp,sharp-quote,Lambda,Lisp,Elisp,Common Lisp,Sharp Quote,这是在通用Lisp上的On Lisp中经常使用的一种技术: > (mapcar #'(lambda (x) (+ x 10)) '(1 2 3)) (11 12 13) 为什么需要或甚至可能采用尖锐的报价?lambda表达式返回函数对象,而尖引号从名称返回函数对象。我还听到过关于lambda表达式是否是名称的相互矛盾的信息——特别是在Lisp上,这与标准相矛盾,但他的代码似乎工作正常,这也与标准相矛盾 在elisp。令我惊讶的是,这其中没有讨论词法范围,所以不清楚为什么
> (mapcar #'(lambda (x) (+ x 10))
'(1 2 3))
(11 12 13)
为什么需要或甚至可能采用尖锐的报价?lambda表达式返回函数对象,而尖引号从名称返回函数对象。我还听到过关于lambda表达式是否是名称的相互矛盾的信息——特别是在Lisp上,这与标准相矛盾,但他的代码似乎工作正常,这也与标准相矛盾
在elisp。令我惊讶的是,这其中没有讨论词法范围,所以不清楚为什么它应该与普通Lisp完全不同。但是他说,不带引号的lambda表达式毫无意义,因此,具有讽刺意味的是,有可能引入不带引号的lambda表达式作为带引号的表达式的语法糖。但这与“在Emacs Lisp中,这样的列表是一个有效的表达式,其计算结果为函数对象”的说法相矛盾
这个问题被标记为common-lisp和e-lisp,因为我试图理解这两个问题背后的理论模型,并通过学习它们的差异来学习它们。(更实际地说,我正在尝试学习elisp,但在Common Lisp上发现了很多很好的资源,所以我正在学习这两种语言)。简而言之,你不必尖锐地引用
lambda
,因为它是一个扩展到(函数(lambda…)
,而函数
才是最神奇的
函数
不必要的唯一意义是您不必自己键入它。基本运算符是函数
,而不是λ
。Lambda表达式本身只是普通的列表(它知道如何将函数对象转换为函数对象),而Lambda
只是一个普通的宏。因此,我们把事情弄得相当倒退:lambda表达式返回函数对象并不能排除function
,因为lambda
是用function
来解释的
另外一个问题是,在Emacs Lisp中,以
lambda
开头的列表可以直接作为函数处理,而不必经过function
。CL中的情况并非如此(尽管显式转换以(强制某些列表的函数)
的形式提供)。这一切都与历史有关<代码>(lambda…只是#'(lambda…)
的语法糖。Common Lisp的早期版本没有将lambda
定义为宏。如果您阅读(PD,第2页),您会看到他明确表示您需要创建如下宏:
(defmacro lambda (args &body body)
"Allow (lambda (x) ...) instead of #'(lambda (x) ...)"
`#'(lambda ,args .,body))
因此,今天在编写(lambda…
时,标准宏会将其重写为#'(lambda…
)
是一本旧书,它可能在宏成为标准之前首次出版。也可能是保罗·格雷厄姆(Paul Graham)习惯于写#'(lambda…
),并且一直坚持写下去
我已经看到,当符合更新的标准时,计算机书籍的后期版本通常会尽可能少地改变。我不确定这是件好事 假定使用公共Lisp
为什么需要或甚至可能采用尖锐的报价
如果要从函数名(特别是要引用词法绑定)或lambda表达式计算函数对象,则需要特殊运算符函数
,或更短的#'
lambda表达式返回函数对象
他们没有甚至无法计算Lambda表达式。
在Common Lisp中,它看起来像是可以计算(lambda()nil)
。但它不能
CLtL1之后的某个时间,添加了一个宏LAMBDA
,将其扩展为(函数…
表达式。这个宏保存了一些输入,让代码看起来更像Scheme。让我们检查一下这个LAMBDA
宏:
CL-USER 17 > (macroexpand-1 '(lambda () ())) ; not a lambda expression
(FUNCTION
(LAMBDA NIL NIL) ; <- this is a lambda expression
)
T
因为上面是一个宏表单,所以将首先展开它,然后对其进行求值
CL-USER 19 > (function ; <- this is a special form
(lambda () ()) ; <- this is a lambda expression
)
#<anonymous interpreted function 4060000C0C>
上面再次显示了lambda表达式。其中,((函数(lambda()))
不是有效的公共Lisp。在函数调用的函数位置,Common Lisp需要函数名或lambda表达式,而不是需要计算的内容
CL-USER 19 > (function ; <- this is a special form
(lambda () ()) ; <- this is a lambda expression
)
#<anonymous interpreted function 4060000C0C>
和尖引号从名称返回函数对象
函数
,它的#
是一个简短的表示法,从函数名或lambda表达式返回函数对象
请参阅文档:
我还听到过关于lambda表达式是否是名称的相互矛盾的信息——特别是在Lisp上,这与标准相矛盾,但他的代码似乎工作正常,这也与标准相矛盾
如果你想听到最后一句话,请阅读ANSI CL标准。或者使用通用的Lisp Hyperspec,它是web可读的,并且源于标准
在Lisp上阅读肯定很有用,但它可能不会完全遵循ANSI CL的措辞或语义。在CLtL2之后,但在ANSI CL之前发布了On Lisp
编写代码的实际意义是什么?
如果您像我一样年纪大了,而且CLtL1是您最后一次阅读Common Lisp的内容,那么请编写如下代码:
(mapcar #'(lambda (x) (* x x)) '(1 2 3))
如果您年纪更大,是在Scheme环境中长大的,或者更年轻,并且已经阅读了常见的Lisp Hyperspec,那么您可能想写:
(mapcar (lambda (x) (* x x)) '(1 2 3))
(mapcar #'sin '(1 2 3))
但对于所有人来说,当涉及函数名时,这是默认的写入方式:
(mapcar (lambda (x) (* x x)) '(1 2 3))
(mapcar #'sin '(1 2 3))
函数
关键字在不同的Lisp语言中似乎有不同的含义
在Lisp1.5中,它用于使用funarg
设备创建闭包。
参考:,以及LISP 1.5程序员手册,附录B
在MacLisp中,它被用作编译器的提示,表示lambda表达式可以编译为代码。参考文献:。它不是用来创建闭包的;*函数
特殊形式也做了类似的事情。参考资料
在Emacs Lisp中,它是对编译器的提示,并且