2010-09-21 12 views
7

Est-il possible d'écrire une macro dans Clojure qui génère plus d'une valeur ou expression? Pour moi, il semble que ce ne soit pas possible, du moins pas en utilisant le modèle de citation syntaxique `(..).Comment écrire une macro Clojure pour créer plusieurs expressions?

par exemple. à partir de: [1 4] via [1 (mr 2 3) 4] à [1 2 3 4]

ou à partir de:

(do 
    (prn 1) 
    (prn 4)) 

via:

(do 
    (prn 1) 
    (mr 2 3) 
    (prn 4)) 

à:

(do 
    (prn 1) 
    (prn 2) 
    (prn 3) 
    (prn 4)) 

Répondre

10

Une macro se développe une forme en une autre forme, de sorte que vous ne peut pas avoir une macro retour deux complètement indépendant f orms. Cependant, vous pouvez le faire renvoyer des formulaires composés comme do déclarations qui font un tas de choses.

(defmacro foo [n] 
    `(do [email protected](map #(list println %) n))) 

Pour votre exemple ci-dessus, vous pouvez mettre la macro autour de la forme que vous souhaitez modifier:

(expand-mr 
(do 
    (prn 1) 
    (mr 2 3) 
    (prn 4))) 

macros sont conçues pour être en sécurité et en tant que tels, ils ne peuvent rien modifier en dehors de leur propre portée. Actuellement, une macro obtient une expression s et la transforme en une autre expression s plus utile ou utile. Pour qu'une macro renvoie deux expressions-s séparées, elle doit modifier son expression englobante. La syntaxe devrait être radicalement différente et je ne sais pas comment cela se ferait avec les expressions-s. La solution consiste à étendre la portée de la macro pour y inclure tout ce dont elle a besoin pour la modifier.

+0

Merci Arthur! J'attendais déjà cette réponse, mais c'est bien d'être sûr. – Stefan

+0

Mais pouvez-vous réellement me donner un exemple de la façon dont une macro retournant deux formulaires indépendants peut causer un problème de sécurité, mais est-il sûr sinon? Je pense que la portée est toujours la même. – Stefan

+0

J'utilise le terme 'safe', désolé, à ce sujet. Je vais modifier pour développer cela. –