2017-03-19 72 views
0

我的问题很简单(可能是误导性的)。Common Lisp EVAL函数语录

在Common Lisp的,当我运行下面的命令,我得到了相应的结果:

(eval '''boo) => 'boo 

如果,另一方面,我运行下面的命令,我得到的东西略有不同。

(eval (eval '''boo)) => boo 

我的问题是:如果第一个命令的eval“刮胡子了”从变量符号两个引号,并在输出1马克离开它,它怎么可能是两个嵌套eval函数取关掉三个引号?

,这是特别令人迷惑,因为在错误的结果如下:

(eval 'boing) => ERROR. BOING is unbound. 

回答

3

eval是一个函数。在对其应用eval之前评估其论点。这就是为什么eval“削掉”两个引号。一个是通过函数应用程序的隐式评估来移除的,另一个是由eval应用程序本身。

但是,当您调用(eval (eval '''boo))时,将外部eval应用于从内部eval返回的值'boo。相当于(eval ''boo)

当您尝试(eval 'boing)该参数在eval应用于它之前被评估,所以eval试图评估boing并出错。

对比这与eval宏版本不适用eval之前评估其参数...

? (defmacro meval (form) `(eval ',form))   
MEVAL 
? (meval 'foo) 
FOO 
? (meval '''foo) 
''FOO 
7

'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)) 
4

第一个问题:

Evaluating (eval '''boo) 

    Evaluating '''boo 
    Result: ''boo 

    Calling Function EVAL with ''boo 
    Function EVAL returns 'boo 

Result: 'boo 

第二个问题:

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