2010-09-20 8 views
3

Petite aide ici s'il vous plait. J'essaie de créer cette macro Lisp qui prend une liste (de nombres) en entrée et retourne la somme de ces nombres. Le codeMacro Lisp basique Question

(setf g (list 1 2 3 4)) 



(defmacro add-test(var) 

    `(+ ,@var)) 

(ajouter test g) donne cette erreur

***** La valeur G est pas de type LIST. [Condition de type TYPE-ERREUR] *****

En même temps (add-test (1 2 3 4)) donne le résultat correct qui est 10.

Pouvez-vous s'il vous plaît expliquer, pourquoi ne fonctionne-t-il pas quand la variable est transmise à la fonction?

Autres détails -

Lispbox - SBCL

Ubuntu Linux

Merci à l'avance

Répondre

8

C'est facile et l'une des questions macro les plus courantes.

(add-test g) 

maintenant sur l'expansion macro, la macro ADD-TEST est appelée avec le paramètre VAR obtenir la valeur G, un symbole.

Ensuite, vous essayez une opération de liste. L'expression backquote

`(+ ,@var) 

La valeur de VAR est G, et vous essayez d'épissure dans la liste (+ ...). L'expression renvoyée est maintenant (+ . G).

CL-USER 12 > (macroexpand '(add-test g)) 
(+ . G) 
T 

(+ . G) n'est pas une forme Lisp valide. Ce n'est pas un code source valide. Rappelez-vous que les paramètres d'une macro sont les expressions source non évaluées.

Comparez cela avec les éléments suivants:

CL-USER 13 > (macroexpand '(add-test (1 2 3 4))) 
(+ 1 2 3 4) 
T 

Vous avez dit: «Pouvez-vous s'il vous plaît expliquer, pourquoi est-il ne fonctionne pas lorsque la variable est passée à la fonction? Rappelez-vous, ADD-TEST n'est PAS une fonction, c'est une macro. Une macro obtient le code source transmis et retourne un nouveau formulaire - ce formulaire est ensuite évalué plus tard.

+0

Merci Rainer pour la réponse détaillée. Cela a beaucoup aidé. – bdev

+0

Par curiosité, disons que nous prenons l'idée de bdev plus loin. Supposons que j'ai une sorte d'expression optimisable (une liste d'entiers!), Et je veux optimiser l'expression avant "run-time". Comment ferais-je cela? (bien que je suppose que (eval G) pourrait fonctionner ...). –

+2

@Paul Nathan: vous pouvez l'ÉVALUER, le COMPILER, le FONCER, l'APPLIQUER - il n'y a presque pas de limites. Voir aussi DEFINE-COMPILER-MACRO, qui vous permet d'écrire des optimisations. –