2017-03-19 2 views
0

Ma question est plutôt simple (peut-être trompeuse).Common Lisp EVAL Fonction Citations

En Common Lisp, quand je lance la commande suivante, je reçois les résultats correspondants:

(eval '''boo) => 'boo 

Si, d'autre part, je lance la commande suivante je reçois quelque chose de légèrement différent.

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

Ma question est la suivante: si la première commande eval de « rase » deux guillemets du symbole variable et laisse une marque à la sortie, comment est-il possible que les deux eval imbriquées les fonctions prennent sur un total de trois guillemets?

Cela est particulièrement déroutant, car les résultats suivants: une erreur

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

Répondre

3

eval est une fonction. Son argument est évalué avant que eval ne lui soit appliqué. C'est pourquoi il semble que eval "rase" deux guillemets. L'un est supprimé par l'évaluation implicite de l'application de la fonction, l'autre par l'application eval elle-même.

Mais quand vous évoquez (eval (eval '''boo)) la eval extérieure est appliquée à la valeur 'boo qui est renvoyée par la eval intérieure. L'équivalent est (eval ''boo).

Lorsque vous essayez (eval 'boing) l'argument est évalué avant eval est appliquée, de sorte eval tente d'évaluer boing et va mal.

contraste avec une version macro de eval qui n'évalue pas son argument avant d'appliquer eval ...

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

'boo est une abréviation pour (quote boo). Dans le code, quote est une forme spéciale qui évalue à quel que soit son argument et rien de plus. Ainsi, boo. Lorsque cette valeur est transmise autour de ses données et non plus le code, mais afin de créer le symbole foo vous avez besoin de quote.

'''boo est l'abréviation de (quote (quote (quote boo))). En l'évaluant il fait exactement comme avant et il devient (quote (quote boo)), une liste avec deux éléments où le deuxième élément est une liste de deux éléments.

Puisque eval est une fonction, il évalue d'abord l'argument, puis il évalue le résultat comme la fonction est supposée le faire. Ainsi (quote (quote foo)) devient (quote foo) après la première évaluation et eval enlève la seconde en laissant le symbole foo.

Si eval obtient un symbole foo, cela signifie qu'il est censé obtenir la valeur liée par la variable foo dans l'espace de noms global. Ainsi:

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

Depuis l'argument est (quote *test*) qui, après évaluation devient *test*.eval voit le symbole et récupère la valeur, 5, qui est le résultat. Si *test* n'est pas lié, vous obtenez l'erreur que vous avez.

(defparameter *test-symbol* '*test) 
(eval *test-symbol*) 

Même ici. Puisque c'est une fonction *test-symbol* est évaluée au symbole *test*, c'est ce que eval voit et il récupère la valeur 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 

Parfois, je vois des débutants faire quelque chose comme '('(a) '(b)). C'est une erreur car quand vous êtes évalué vous finissez avec la liste ((quote (a)) (quote (b))) comme les données et c'est rarement l'intention. Lorsque vous utilisez une fonction comme list les arguments évalués et obtient vous devez citer correctement:

(list '(a) *result* '(b)) 
; ==> ((a) (quote foo) (b)) 
4

Première question:

Evaluating (eval '''boo) 

    Evaluating '''boo 
    Result: ''boo 

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

Result: 'boo 

Deuxième question:

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