gpt4 book ai didi

lambda - Common Lisp 中的 lambda 表达式是宏还是标记?

转载 作者:行者123 更新时间:2023-12-05 08:36:50 24 4
gpt4 key购买 nike

我正在尝试通过Common Lisp:对符号计算的温和介绍这本书来学习 Common Lisp。此外,我正在使用 SBCL、Emacs 和 Slime。

在第 7 章中,作者提出了以下关于 lambda 表达式 的建议: enter image description here

这让我感到困惑,因为 SBCL 的 REPL 返回:

CL-USER> #'lambda
#<CLOSURE (:MACRO LAMBDA) {1000D736DB}>

显然,作者使用了 Lisp Works(并非 100% 确定)。我认为这与上述差异无关。不过,我认为还是提一下比较好。

我的 SBCL 的 REPL 还为众所周知的宏返回 macro,例如 :

CL-USER> #'and
#<CLOSURE (:MACRO AND) {1000D7365B}>

请注意,append 等“普通”函数的行为是不同的:

CL-USER> #'append
#<FUNCTION APPEND>

此帖here似乎略微触及了 lambda 表达式的非单一性。但是,它没有提及任何关于标记的内容。

我是不是漏掉了 lambda 表达式的本质?

最佳答案

思考这个问题的一种方式是认识到在 CL 中获得词法上明显的函数值的唯一方法是特殊运算符 function : 如果你想获得与 foo 关联的函数在当前的词汇环境中你必须说(function foo) :

(flet ((foo (x)
x))
(function foo)

例如。所以function是特殊的运算符,它可以让您查看函数命名空间中的内容。 function有一些语法糖,即 #' , 同理quote确实(我不打算在下面使用它)。你可以想到函数应用 (f x y)大约像(<funcall> (function f) x y) , 其中<funcall>是一些神奇的东西,它不会像那样被替换掉。

但是您还需要匿名函数,那么,您可以使用 function同样,它的参数是一个 lambda 表达式:

lambda expression n. a list which can be used in place of a function name in certain contexts to denote a function by directly describing its behavior rather than indirectly by referring to the name of an established function; its name derives from the fact that its first element is the symbol lambda. – CLHS

所以匿名函数表示为(function (lambda (...) ...)) .如果你愿意,你可以想到 (lambda (...) ...)作为函数的“名称”。 (我认为人们不喜欢这个,因为它干扰了匿名函数的想法,但很明显,有一组可数的可能函数“名称”,形式为 (lambda (...) ...),你甚至可以枚举这组我认为(这样做与枚举有理数一样繁琐)。

由于函数应用程序中的函数位置已经在函数的命名空间中被解释,((lambda (...) ...) ...)表示匿名函数应用程序:它或多或少与 (funcall (function (lambda (...) ...) ...) 相同(再次参见 CLHS)。

这就是 CL 在 1980 年代某个时候的样子。

然后有一些我不确定的历史混淆:我记得它发生但我不记得顺序。首先,在 Lisp-1 中你不需要任何 function东西:表格 car表示获取 conscar 的函数,你不需要说 (function car) .同样(lambda (...) ...)表示一个函数。除此之外还有另一个提议的 Lisp 标准,它是/是 ISLisp,可能是 here .尽管 ISLisp 不是 Lisp-1,它确实有一个形式 (lambda (...) ...)表示一个函数。

人们希望 CL 能够与 ISLisp 兼容,这意味着 (lambda (...) ...)应该表示一个函数。每个人实际上所做的是偷偷添加一个定义,例如:

(defmacro lambda (args &body forms)
`(function (lambda ,args ,@forms)))

但是,至关重要的是,您不能在 CL 中以可移植的方式执行此操作,因为 lambdacl:lambda并且您不得重新定义 CL 包中的内容。人们还是这样做了,但结果是他们的程序不可移植,而且经常不得不用特殊的魔法装饰来解锁和重新锁定CL。包。

好吧,解决方案是语言 必须提供这样一个宏。在 CLtL1 定义的语言和最终标准之间的某个时候,这发生了,所以现在 lambda有一个宏定义,其扩展是(或多或少:实现可能被允许做特殊的事情)明显的扩展:

(lambda (x) x)
-> #'(lambda (x) x)

所以在现代 CL 中:

  • 列表开始lambda表示('names')形式为 (function (lambda (...) ...) 的函数并且在表单的函数位置,所以 ((lambda (x) x) 1) , 说。
  • lambda被定义为扩展为 (function (lambda (...) ...)) 的宏这使得它更易于使用。

注意:我认为您正在使用的实现允许执行它对宏所做的操作,但您不应该依赖于此:

It is an error to use function on a function name that does not denote a function in the lexical environment in which the function form appears. Specifically, it is an error to use function on a symbol that denotes a macro or special form. An implementation may choose not to signal this error for performance reasons, but implementations are forbidden from defining the failure to signal an error as a useful behavior. – CLHS

你真的应该使用 macro-function它会告诉您某些东西是否有宏定义。

关于lambda - Common Lisp 中的 lambda 表达式是宏还是标记?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67642412/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com