我的问题很简单(也许是误导性的)。
在Common Lisp中,当我运行以下命令时,会得到相应的结果:

(eval '''boo) => 'boo

另一方面,如果我运行下面的命令,就会得到一些稍微不同的结果。
(eval (eval '''boo)) => boo

我的问题是:如果第一个命令的eval“去掉”变量符号的两个引号,并在输出处留下一个,那么两个嵌套的eval函数怎么可能总共去掉三个引号?
这尤其令人困惑,因为以下情况会导致错误:
(eval 'boing) => ERROR. BOING is unbound.

最佳答案

'boo(quote boo)的缩写在代码中,quote是一种特殊的形式,它的计算结果与参数无关因此boo当这个值被传递到它的数据周围时,不再编码,而是为了创建符号foo,您需要quote
'''boo(quote (quote (quote boo)))的缩写当对它进行求值时,它与以前完全一样,变成(quote (quote boo)),一个包含两个元素的列表,其中第二个元素是一个包含两个元素的列表。
因为eval是一个函数,所以它首先计算参数,然后像函数应该做的那样计算结果因此,第一次评估后(quote (quote foo))变为(quote foo)eval去掉第二次,留下符号foo
如果eval得到一个符号foo,则意味着它应该得到由全局命名空间中的变量foo绑定的值因此:

(defparameter *test* 5)
(eval '*test*)
; ==> 5

因为参数是(quote *test*),在求值之后变为*test*eval看到符号并获取结果值5如果*test*未绑定,则会得到所得到的错误。
(defparameter *test-symbol* '*test)
(eval *test-symbol*)

彼此彼此。因为它是一个函数*test-symbol*被计算为符号*test*,这就是eval所看到的,它获取值5
(defparameter *result* (eval '''foo))
*result*
; ==> (quote foo) but often the REPL shows 'foo
(consp *result*)
; ==> t
(length *result*)
; ==> 2
(car *result*)
; ==> quote
(cadr *result*)
; ==> foo

有时我看到初学者做一些类似于'('(a) '(b))的事情这是一个错误,因为当你评估时,你最终得到的是列表((quote (a)) (quote (b)))作为数据,而这很少是你的意图当使用类似于list的函数时,将计算参数,并且需要适当地引用:
(list '(a) *result* '(b))
; ==> ((a) (quote foo) (b))

关于lisp - Lisp通用EVAL函数报价,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42887151/

10-14 06:12