我的问题很简单(可能具有误导性)。
在 Common Lisp 中,当我运行以下命令时,我得到了相应的结果:
(eval '''boo) => 'boo
另一方面,如果我运行以下命令,我会得到一些稍微不同的东西。
(eval (eval '''boo)) => boo
我的问题是:如果第一个命令的 eval
从 variable-symbol 中“削掉”两个引号并在输出中留下一个标记,这两个嵌套怎么可能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
取消第二次留下符号 富
。
如果 eval
得到一个符号 foo
,这意味着它应该得到全局命名空间中变量 foo
绑定(bind)的值。因此:
(defparameter *test* 5)
(eval '*test*)
; ==> 5
因为参数是 (quote *test*)
,在评估后变成了 *test*
。 eval
查看符号并获取值 5
,这就是结果。如果 *test*
没有绑定(bind),你会得到你得到的错误。
(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 - Common Lisp EVAL 函数引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42887151/