为什么要用尖锐的报价lambda表达式? [英] Why sharp quote lambda expressions?

查看:89
本文介绍了为什么要用尖锐的报价lambda表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是常见于Lisp的 Lisp 中常用的一种技术:

> (mapcar #'(lambda (x) (+ x 10))
         '(1 2 3))
(11 12 13)

为什么需要甚至可能使用尖引号? lambda表达式返回函数对象,尖引号从名称返回函数对象.我还听说过有关lambda表达式是否为名称的矛盾信息-特别是在Lisp上与标准相抵触,但他的代码似乎有效,也与标准相抵触.

在elisp 中似乎根本不需要.令我惊讶的是,这里没有讨论词法范围,因此不清楚为什么它应该与Common Lisp完全不同.但是此答案表示未引用的lambda表达式毫无意义,因此,具有讽刺意味的是,可以引入未引用的lambda表达式作为引号的语法糖.但这与 elisp手册的主张表示在Emacs Lisp中,这样的列表是有效的表达式,其结果为函数对象."

这个问题被标记为常见和错误,因为我试图理解两者的理论模型,并通过学习它们的差异来学习它们. (实际上,我试图学习elisp,但是在Common Lisp上发现了很多很好的资源,所以都被这两者所吸引.)

解决方案

假定使用通用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

这意味着,如果您评估(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>

由于上面是宏形式,将首先对其进行扩展,然后再对其进行求值.

CL-USER 19 > (function          ; <- this is a special form
              (lambda () ())    ; <- this is a lambda expression
              )
#<anonymous interpreted function 4060000C0C>

这里确实是lambda表达式.在特殊运算符FUNCTION内部,该表格将不会进行宏扩展或类似操作.

CL-USER 20 > (                  ; <- this is a function call
              (lambda () ())    ; <- this is a lambda expression
              )

再次在上方显示lambda表达式. ((function (lambda () ())))无效的通用Lisp.在函数调用的函数位置,Common Lisp期望使用函数名称或lambda表达式,但不需要进行评估.

并用引号引起来,从名称中返回函数对象.

FUNCTION(其缩写为#')从函数名称 lambda表达式返回函数对象.

请参阅文档:功能.

我也听说过有关lambda表达式是否为名称的矛盾信息-特别是在Lisp上与标准相矛盾,但是他的代码似乎也与标准相矛盾.

如果您想听最后一个单词,请阅读ANSI CL标准.另外,也可以使用Common Lisp Hyperspec,它是Web可读的,并且是从该标准派生的.

在Lisp上阅读绝对是有用的,但它可能未完全遵循ANSI CL的措辞或语义. 《关于Lisp》是在CLtL2之后但在ANSI CL之前发布的.

编写代码时实际上意味着什么?

如果您像我一样老了,而CLtL1是您读过的Common Lisp的最后一本书,则编写如下代码:

(mapcar #'(lambda (x) (* x x)) '(1 2 3))

如果您年龄更大并且在Scheme上长大,或者您更年轻并且已阅读Common Lisp Hyperspec,那么您可能要写:

(mapcar (lambda (x) (* x x)) '(1 2 3))

但是对于所有函数名称而言,这是默认的写法:

(mapcar #'sin '(1 2 3))

It is a technique used frequently in On Lisp, which is on Common Lisp:

> (mapcar #'(lambda (x) (+ x 10))
         '(1 2 3))
(11 12 13)

Why is sharp-quote needed or even possible? lambda expressions return function objects, and sharp quoting returns function objects from names. I also have heard contradictory information on whether lambda expressions are names - in particular On Lisp contradicts the standard, but his code seems to work which also contradicts the standard.

In elisp it seems it's not needed at all. To my surprise this included no discussion of lexical scope, so it's unclear why it should be different from Common Lisp at all. But this answer says that unquoted lambda expressions make no sense whatsoever, hence, ironically, it was possible to introduce unquoted lambda expressions as syntactic sugar for quoted ones. But this contradicts the elisp manual's claim that "In Emacs Lisp, such a list is a valid expression which evaluates to a function object."

This question is tagged both common- and e- lisp because I'm trying to understand the theoretical model underlying both, and learn them by learning their differences. (More practically I'm trying to learn elisp but found lots of good resources on Common Lisp so am caught up learning both).

解决方案

Common Lisp assumed.

Why is sharp-quote needed or even possible?

If you want to compute a function object from a function name (especially if you want to refer to a lexical binding) or a lambda expression, you need the special operator FUNCTION, or shorter #'.

lambda expressions return function objects,

They don't. Lambda expressions can't even be evaluated.

In Common Lisp it looks like (lambda () nil) can be evaluated. But it can't.

Sometime after CLtL1 a macro LAMBDA has been added that expands it into a (FUNCTION ...) expression. This macro saves some typing and let's code look a bit more like Scheme. Let's check this LAMBDA macro:

CL-USER 17 > (macroexpand-1 '(lambda () ()))  ; not a lambda expression
(FUNCTION 
  (LAMBDA NIL NIL)                            ; <- this is a lambda expression
)
T

This means that the following happens if you evaluate (lambda () ()):

  • LAMBDA is a macro. Thus the form gets expanded to (function (lambda () ())).
  • (function (lambda () ())) -> FUNCTION is a special operator. It returns a function object
  • ->

If you write: #'(lambda () ()) or (function (lambda () ())), then you'll skip the macro expansion.

Okay, now for something strange:

CL-USER 18 > (lambda () ())   ; <- this is not a lambda expression.
                              ;    it's a macro form, see above 
#<anonymous interpreted function 40600009FC>

Because above is a macro form, it will be expanded first and then it can be evaluated.

CL-USER 19 > (function          ; <- this is a special form
              (lambda () ())    ; <- this is a lambda expression
              )
#<anonymous interpreted function 4060000C0C>

Here it really is a lambda expression. Inside the special operator FUNCTION the form will not be macro expanded or similar.

CL-USER 20 > (                  ; <- this is a function call
              (lambda () ())    ; <- this is a lambda expression
              )

Above again, shows a lambda expression. Where ((function (lambda () ()))) is not valid Common Lisp. In the function position of a function call, Common Lisp expects either a function name or a lambda expression, but not something which needs to be evaluated.

and sharp quoting returns function objects from names.

FUNCTION, for which #' is a short notation, returns function objects from function names or lambda expressions.

See the documentation: FUNCTION.

I also have heard contradictory information on whether lambda expressions are names - in particular On Lisp contradicts the standard, but his code seems to work which also contradicts the standard.

If you want to hear the last word, read the ANSI CL standard. Alternatively use the Common Lisp Hyperspec, which is web-readable and derived from the standard.

On Lisp is definitely useful to read, but it might not follow the wording or semantics of ANSI CL in full detail. On Lisp was published after CLtL2, but before ANSI CL.

What does it mean practically when writing code?

If you are old, like me, and CLtL1 was the last thing you read of Common Lisp then write code like:

(mapcar #'(lambda (x) (* x x)) '(1 2 3))

If you are even older and grew up with Scheme, or are younger and have read the Common Lisp Hyperspec, then you might want to write:

(mapcar (lambda (x) (* x x)) '(1 2 3))

But for all, when it comes to function names, this is the default to write:

(mapcar #'sin '(1 2 3))

这篇关于为什么要用尖锐的报价lambda表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆