dje*_*lin 14 lisp lambda elisp common-lisp sharp-quote
它是On Lisp中经常使用的一种技术,它位于Common Lisp上:
> (mapcar #'(lambda (x) (+ x 10))
'(1 2 3))
(11 12 13)
Run Code Online (Sandbox Code Playgroud)
为什么需要锐利报价甚至可能?lambda表达式返回函数对象,而尖锐的引用从名称返回函数对象.我也听说过关于lambda表达式是否是名称的矛盾信息 - 特别是On Lisp与标准相矛盾,但是他的代码似乎也与标准相矛盾.
在elisp中,似乎根本不需要它.令我惊讶的是,这里没有讨论词法范围,因此不清楚为什么它应该与Common Lisp完全不同.但是这个答案说不带引号的lambda表达式没有任何意义,因此,具有讽刺意味的是,有可能引入不带引号的lambda表达式作为引用的语法糖.但这与elisp手册中的声明相矛盾,即"在Emacs Lisp中,这样的列表是一个有效的表达式,可以计算出一个函数对象."
这个问题被标记为普通和e-lisp,因为我试图理解两者的理论模型,并通过了解它们的差异来学习它们.(更实际的是,我正在尝试学习elisp,但在Common Lisp上找到了很多很好的资源,所以我很想学习它们).
Rai*_*wig 19
Common Lisp假定.
为什么需要锐利报价甚至可能?
如果要从函数名称计算函数对象(特别是如果要引用词法绑定)或lambda表达式,则需要特殊运算符FUNCTION或更短的运算符#'.
lambda表达式返回函数对象,
他们没有.甚至无法评估Lambda表达式.
在Common Lisp中,它看起来(lambda () nil)可以被评估.但它不能.
在CLtL1之后的某个时候添加了一个宏LAMBDA,将其扩展为(FUNCTION ...)表达式.这个宏节省了一些打字,让我们的代码看起来更像Scheme.我们来看看这个LAMBDA宏:
CL-USER 17 > (macroexpand-1 '(lambda () ())) ; not a lambda expression
(FUNCTION
(LAMBDA NIL NIL) ; <- this is a lambda expression
)
T
Run Code Online (Sandbox Code Playgroud)
这意味着如果您评估,会发生以下情况(lambda () ()):
LAMBDA是一个宏.因此表格扩展到(function (lambda () ())).(function (lambda () ()))- > FUNCTION是一个特殊的运营商.它返回一个函数对象如果您写:#'(lambda () ())或者(function (lambda () ())),那么您将跳过宏扩展.
好的,现在有些奇怪了:
CL-USER 18 > (lambda () ()) ; <- this is not a lambda expression.
; it's a macro form, see above
#<anonymous interpreted function 40600009FC>
Run Code Online (Sandbox Code Playgroud)
因为上面是一个宏形式,它将首先展开,然后可以进行评估.
CL-USER 19 > (function ; <- this is a special form
(lambda () ()) ; <- this is a lambda expression
)
#<anonymous interpreted function 4060000C0C>
Run Code Online (Sandbox Code Playgroud)
这里真的是一个lambda表达式.在特殊运算符内部,FUNCTION表单不会被宏扩展或类似.
CL-USER 20 > ( ; <- this is a function call
(lambda () ()) ; <- this is a lambda expression
)
Run Code Online (Sandbox Code Playgroud)
再次,上面显示了lambda表达式.哪里((function (lambda () ())))无效Common Lisp.在函数调用的函数位置,Common Lisp需要函数名或lambda表达式,而不是需要计算的东西.
和尖锐的引用从名称返回函数对象.
FUNCTION,为#'简短表示法,从函数名或 lambda表达式返回函数对象.
请参阅文档:功能.
我也听说过关于lambda表达式是否是名称的矛盾信息 - 特别是On Lisp与标准相矛盾,但是他的代码似乎也与标准相矛盾.
如果您想听到最后一个字,请阅读ANSI CL标准.或者使用Common Lisp Hyperspec,它是Web可读的并且源自标准.
在Lisp上读取绝对有用,但它可能不完全遵循ANSI CL的措辞或语义.关于Lisp是在CLtL2之后发布的,但是在ANSI CL之前发布.
编写代码时实际意味着什么?
如果你像我一样老了,而且你读过Common Lisp的最后一件事是CLtL1那么就写下代码:
(mapcar #'(lambda (x) (* x x)) '(1 2 3))
Run Code Online (Sandbox Code Playgroud)
如果你年纪大了并且已经和Scheme一起长大,或者更年轻并且已经阅读了Common Lisp Hyperspec,那么你可能想写:
(mapcar (lambda (x) (* x x)) '(1 2 3))
Run Code Online (Sandbox Code Playgroud)
但是对于所有人来说,当涉及到函数名称时,这是默认编写:
(mapcar #'sin '(1 2 3))
Run Code Online (Sandbox Code Playgroud)
简而言之,你不必尖锐引用,lambda因为它是一个扩展到的宏,(function (lambda ...))它就是function所有的魔力.
唯一function没有必要的意义是你不必自己打字.这是function,不lambda,这是基本的操作员.Lambda表达式本身只是普通的列表(它function知道如何变成函数对象),而且lambda只是一个普通的宏.所以你有一些相反的东西:lambda表达式返回函数对象并没有消除,function因为它lambda是用来解释的 function.
另一个问题是,在Emacs Lisp中,开头的列表lambda可以直接作为函数处理,而无需经过function.在CL中不是这种情况(尽管可以以形式获得显式转换(coerce some-list 'function)).
这一切都与历史有关。(lambda ...)只是#'(lambda ..). Common Lisp 的早期版本没有lambda定义为宏。例如。如果您阅读Peter Norvigs 关于 Quines 的文章(PD,第 2 页),您会看到他明确指出您需要创建这样的宏,如下所示:
(defmacro lambda (args &body body)
"Allow (lambda (x) ...) instead of #'(lambda (x) ...)"
`#'(lambda ,args .,body))
Run Code Online (Sandbox Code Playgroud)
因此,在(lambda ...)今天编写时,标准宏会将其重写为#'(lambda ...).
On Lisp是一本旧书,它可能在宏成为标准之前就已经出版了。也可能是保罗格雷厄姆习惯于写作#'(lambda ...)并坚持下去。
我已经看到,当符合更新的标准时,计算机书籍的后续版本通常会尽可能少地更改。我不确定这是一件好事。
| 归档时间: |
|
| 查看次数: |
1719 次 |
| 最近记录: |