我的问题很简单(也许是误导性的)。
在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/