Lisp 口齿不清:为什么“eval”在引入词汇作用域后失去了人们的青睐?

Lisp 口齿不清:为什么“eval”在引入词汇作用域后失去了人们的青睐?,lisp,eval,Lisp,Eval,刚刚在《人工智能编程范例》中看到Peter Norvig的一句话: 在过去,eval被视为Lisp灵活性的关键。在里面 使用了具有词汇范围的现代Lisp,例如Common Lisp,eval 不太经常(事实上,在方案中根本没有评估)。相反 程序员应该使用lambda来创建一个新函数,并且 然后应用或函数化所有函数 关于为什么eval不是一个好主意,有一些考虑,例如,我更感兴趣的是eval和动态(特殊?)变量之间的相互作用,以及词汇的引入如何导致eval失宠。在引入词汇变量之前,有哪些常见的eva

刚刚在《人工智能编程范例》中看到Peter Norvig的一句话:

在过去,eval被视为Lisp灵活性的关键。在里面 使用了具有词汇范围的现代Lisp,例如Common Lisp,eval 不太经常(事实上,在方案中根本没有评估)。相反 程序员应该使用lambda来创建一个新函数,并且 然后应用或函数化所有函数

关于为什么eval不是一个好主意,有一些考虑,例如,我更感兴趣的是
eval
和动态(特殊?)变量之间的相互作用,以及词汇的引入如何导致
eval
失宠。在引入词汇变量之前,有哪些常见的
eval
习语?

在当前动态环境和空词汇环境中计算表单

这意味着

(defun f (a) (eval '(1+ a)))
; warning: The variable A is defined but never used.
编译器注意到,与天真的期望相反,
a
没有传递给
eval
。 事实上:


不幸的是,我手边没有引文,但从我记忆中听到的,该文本可能引用的模式是模拟词汇范围的一种方式。也就是说,在词汇公共Lisp中,我们可以简单地编写:

(defun constant-adder (a)
  (lambda (b) (+ a b)))
在对所有变量使用动态范围的语言中(但在其他情况下使用相同的语法),可以通过构造lambda表达式来模拟词法范围:

(defun constant-adder (a)
  (eval `(lambda (b) (+ (quote ,a) b))))
也就是说,我们正在运行时构造一个表达式,该表达式中替换了
a
的值,而不是让语言自动捕获
a

(然而,您的报价表明,也没有使用
lambda
。我没有合理的解释说明在这种情况下会发生什么。)

这与实际情况类似。
(defun constant-adder (a)
  (eval `(lambda (b) (+ (quote ,a) b))))