lambda - Lisp 代码数据对偶性、Lambda 表达式是常量吗?

标签 lambda closures lisp common-lisp

我正在关注 Paul Graham 的《On Lisp》一书,其中第 5.7 节说“尖引号 lambda 表达式是常量,但对构造函数的调用将在运行时进行评估。 ”

这让我想起了 Lisp 代码数据二元性的一般原则。

有人可以帮忙解释一下函数在计算机内存中表示时如何是常数吗?当然,这只是一组指令,但函数仍然接受输入,所以这是否意味着运行时的实际执行不是恒定的?

最佳答案

这意味着函数是一个不能被修改的常量对象。就像一把铲子:你不能更换铲子,但你可以用它挖许多不同的沟渠。同样,您无法更改该函数,但可以将其应用于不同的参数并获取不同的值。

顺便说一句,对于所有实现来说,情况并不一定总是如此。 例如,在CLISP中:

(defun f(x) (+ x 10))
(compile 'f)
(f 5)
==> 15
(disassemble #'f)

Disassembly of function F
(CONST 0) = 10
1 required argument
0 optional arguments
No rest parameter
No keyword parameters
4 byte-code instructions:
0     (CONST&PUSH 0)                      ; 10
1     (LOAD&PUSH 2)
2     (CALLSR 2 55)                       ; +
5     (SKIP&RET 2)

很简单吧?

现在,如果您使用 CLISP 的内部功能修改其常量向量并将 10 替换为其他内容,您将更改函数的行为:

(setf (sys::closure-const #'f 0) 42)
(f 7)
==> 49

这类似于在调试器下运行 C 程序并修改局部变量。

另请参阅Why does an elisp local variable keep its value in this case?Why does this function return a different value every time?

PS。请注意,这样做可能会导致严重崩溃(段错误)。当心。

关于lambda - Lisp 代码数据对偶性、Lambda 表达式是常量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64717429/

相关文章:

c++ - 为什么在模板化 lambda 时编译器生成的代码不同?

python - lambdas 有什么用?

javascript - 向回调添加额外参数

lisp - Scheme 中的列表操作

c# - 使用对象初始值设定项创建实例的表达式

c# - 如何将 Expression<Func<T, object>> 转换为 Expression<Func<object, object>>

swift - 如何在函数中抛出一个闭包?

用于列表清理的Java one liner

lisp - 方案: "expects 1 argument, given 4"奇怪的行为

for-loop - cl-loop 破坏性地修改 cons 单元格