2017-05-08 2 views
1

De http://www.gigamonkeys.com/book/practical-a-simple-database.html:"@" dans les fonctions macro Lisp

Le @, "épissures" la valeur de l'expression suivante - qui doit évaluer à une liste - dans la liste englobante. Vous pouvez voir la différence entre et, @ dans les deux expressions suivantes:

`(and ,(list 1 2 3)) ==> (AND (1 2 3)) 

`(and ,@(list 1 2 3)) ==> (AND 1 2 3) 

Même avec l'exemple, je ne peux pas rassembler ce que le ,@ fait. Quelqu'un pourrait-il mentionner explicitement les étapes du deuxième exemple? (Oui, Lisp débutant ici)

+0

Pouvez-vous élaborer sur ce que vous ne comprenez pas? Vous pouvez voir que dans un cas, vous avez toujours des parens, et dans l'autre cas, vous n'avez pas. Vous pouvez penser à ', @' en exécutant simplement une étape supplémentaire à la fin, où il supprime les parens des listes. Comprenez-vous déjà ce que '' '' et ',' font? –

+0

est-ce simplement que '@' supprime la liste? Je pense que je comprends ce que backquote et ',' faire. Backquote = ne sera pas évalué. La virgule sera évaluée. Droite? –

+0

Oui, vous avez raison à propos du backtick et de la virgule. Strictement parlant, je pense que ce que ', @' fait est d'ajouter '. , '. Vous pouvez le voir si vous faites ', @' sur quelque chose qui n'est pas une liste. Le truc c'est que le '.' dit à Lisp de mettre explicitement quelque chose dans la cellule. Cependant, mettre une liste dans la cellule des inconvénients étend simplement la liste actuelle. Fondamentalement, il "dégrippe" la liste. Au lieu d'avoir une liste avec ET comme premier élément et le deuxième élément est une liste imbriquée 1 2 3, vous finissez avec une seule liste parce que 1 2 3 a été ajouté à la liste d'un élément contenant AND. –

Répondre

3

Voici une version légèrement modifiée de votre exemple:

`(foo bar ,(list 1 2 3) baz) ==> (foo bar (1 2 3) baz) 

`(foo bar ,@(list 1 2 3) baz) ==> (foo bar 1 2 3 baz) 

Dans la première expression de la liste (1 2 3) est insérée comme un élément dans la liste des résultats. Dans la deuxième expression, les éléments de la liste (1 2 3) deviennent des éléments dans la liste résultante. Les listes sont "épissées".

2

Notez que la fonction de retour arrière est indépendante de les macros. C'est un mécanisme général pour construire des listes à partir de modèles. Puisque le code source Lisp est basé sur des listes, il est parfois utile de construire du code source Lisp à partir de modèles de code source.

CL-USER 86 > `(one pi ,(* 1 pi) 
       two pi ,(* 2 pi)  
       three pi ,(* 3 pi)) 
(ONE PI 3.141592653589793D0 
TWO PI 6.283185307179586D0 
THREE PI 9.42477796076938D0) 

CL-USER 87 > `((one pi ,(* 1 pi)) 
       (two pi ,(* 2 pi)) 
       (three pi ,(* 3 pi))) 
((ONE PI 3.141592653589793D0) 
(TWO PI 6.283185307179586D0) 
(THREE PI 9.42477796076938D0)) 


CL-USER 90 > `(((one pi) (two pi) (three pi)) 
       ,(loop for i from 1 upto 3 collect (list (* pi i)))) 
(((ONE PI) (TWO PI) (THREE PI)) 
((3.141592653589793D0) (6.283185307179586D0) (9.42477796076938D0))) 

Voici un exemple avec ,@, où la liste des résultats est épissé. La liste des résultats disparaît et ses éléments deviennent membres de la liste de résultats.

CL-USER 91 > `(((one pi) (two pi) (three pi)) 
       ,@(loop for i from 1 upto 3 collect (list (* pi i)))) 
(((ONE PI) (TWO PI) (THREE PI)) 
    (3.141592653589793D0) (6.283185307179586D0) (9.42477796076938D0))