Mad*_*ist 0 lisp eval common-lisp
我的问题很简单(也许是误导性的).
在Common Lisp中,当我运行以下命令时,我得到相应的结果:
(eval '''boo) => 'boo
Run Code Online (Sandbox Code Playgroud)
另一方面,如果我运行以下命令,我会得到一些略有不同的东西.
(eval (eval '''boo)) => boo
Run Code Online (Sandbox Code Playgroud)
我的问题是:如果第一个命令eval从变量符号中"删除"两个引号并在输出处留下一个标记,那么两个嵌套eval函数如何取出总共三个引号?
这特别令人困惑,因为以下结果会导致错误:
(eval 'boing) => ERROR. BOING is unbound.
Run Code Online (Sandbox Code Playgroud)
'boo是.的缩写(quote boo).在代码中,quote是一种特殊的形式,它可以评估任何它的参数,仅此而已.因此boo.当这个值传递给它的数据时,不再是代码,而是为了创建foo你需要的符号quote.
'''boo是.的缩写(quote (quote (quote boo))).在评估它时,它完全像以前一样,它变成(quote (quote boo))了一个包含两个元素的列表,其中第二个元素是两个元素的列表.
因为eval它是一个函数,它首先计算参数,然后它评估结果,因为函数应该这样做.因此在第一次评估之后(quote (quote foo))变为第二次离开符号.(quote foo)evalfoo
如果eval获得符号,foo则意味着它应该获得foo全局命名空间中变量绑定的值.从而:
(defparameter *test* 5)
(eval '*test*)
; ==> 5
Run Code Online (Sandbox Code Playgroud)
由于论证是(quote *test*)在评估之后变成的*test*.eval看到符号并获取值5,这就是结果.如果*test*没有约束,你会得到你得到的错误.
(defparameter *test-symbol* '*test)
(eval *test-symbol*)
Run Code Online (Sandbox Code Playgroud)
同样在这里.因为它是一个函数*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
Run Code Online (Sandbox Code Playgroud)
有时我会看到初学者做的事情'('(a) '(b)).这是一个错误,因为在评估时,您最终将列表((quote (a)) (quote (b)))作为数据,而这很少是意图.当使用像list参数这样的函数进行评估时,你需要适当引用:
(list '(a) *result* '(b))
; ==> ((a) (quote foo) (b))
Run Code Online (Sandbox Code Playgroud)
eval是一个函数。eval它的参数在应用于它之前被评估。这就是为什么看起来eval“删掉”了两个引号。一个是通过函数应用程序的隐式求值来删除的,另一个是通过eval应用程序本身来删除的。
但是,当您调用时,(eval (eval '''boo))外部eval将应用于'boo从内部返回的值eval。等价的是(eval ''boo).
当您尝试时,(eval 'boing)参数会在eval应用于它之前进行评估,因此eval尝试评估boing并会出错。
eval将此与在应用之前不评估其参数的宏版本进行对比eval...
? (defmacro meval (form) `(eval ',form))
MEVAL
? (meval 'foo)
FOO
? (meval '''foo)
''FOO
Run Code Online (Sandbox Code Playgroud)
第一个问题:
Evaluating (eval '''boo)
Evaluating '''boo
Result: ''boo
Calling Function EVAL with ''boo
Function EVAL returns 'boo
Result: 'boo
Run Code Online (Sandbox Code Playgroud)
第二个问题:
Evaluating (eval (eval '''boo))
Evaluating (eval '''boo)
Evaluating '''boo
Result: ''boo
Calling EVAL with ''boo
Function EVAL returns 'boo
Calling Function EVAL with 'boo
Function EVAL returns boo
Result: boo
Run Code Online (Sandbox Code Playgroud)