2011-08-28 5 views
0

Disons que j'ai la macro suivante dans R RS Schéma:Scheme Macros - Pair dans la transformation mais liste en sortie?

(define-syntax pair-test 
    (syntax-rules() 
    ((_ (a b . c)) 
     (quote (a b . c))))) 

La macro transforme une paire d'entrée à une paire de sortie, comme on pouvait s'y attendre:

(pair-test (1 2 . 3)) 
==> (1 2 . 3) 

Je peux aussi passez une liste à la macro, comme le permet la spécification. Cependant, la sortie est une liste au lieu d'une paire:

(pair-test (1 2 3)) 
==> (1 2 3) 

ce qui se passe exactement ici? Pourquoi la sortie est-elle une liste au lieu d'une paire?

Répondre

5

Est-ce que c peut être (3 .()) dans le deuxième cas? Je ne suis pas positif mais cela aurait du sens pour moi. Et puis en citant (a b . c) serait (1 2 . (3 .())) qui est (1 2 . (3)) et (3) est une bonne liste, alors (1 2 3)?

+0

Oui. En fait, c est '(3.()) '--- la citation supplémentaire que vous avez ne devrait pas être là --- mais vous avez essentiellement raison. –

2

Pour voir ce qui se passe ici, vous devez savoir qu'une liste dans Scheme est une chaîne récursive de paires d'éléments et d'autres listes. Toute donnée qui suit la forme d'une liste sera toujours imprimée sous forme de liste. Une fois que vous savez comment sont construites les listes de base, vous pouvez voir ce qui se passe dans votre macro.

Les paires dans Scheme peuvent être créées à l'aide de l'opérateur . ou de la fonction cons. Voici une simple paire de chiffres:

(quote (1 . 2)) 
==> '(1 . 2) 
(cons 1 2) 
==> '(1 . 2) 

Pour créer une liste de 1 dans le schéma, vous pouvez faire une paire de quelque chose et la liste vide:

(quote (1 .())) 
==> '(1) 
(cons 1 (list)) 
==> '(1) 

Une liste de 2 est une paire de quelque chose de quelque chose sur le côté gauche, et une liste de 1 sur le côté droit. De même, une liste de 3 est un élément associé à une liste de 2:

(quote (1 . (2 . (3 .())))) 
==> '(1 2 3) 
(cons 1 (cons 2 (cons 3 (list)))) 
==> '(1 2 3) 

Pour voir ce que votre macro fait, vous pouvez modifier l'(quote (a b . c)) être plus explicite:

(quote (a . (b . c))) 
(cons (quote a) (cons (quote b) (quote c))) 

Maintenant, vous peut voir que cette forme ressemble beaucoup à quand vous construisez une liste. Si (quote c) donne une liste, alors l'expression entière sera une liste. Dans le cas de (pair-test (1 2 3)), c devient (3 .()):

(quote (a . (b . c))) 
==> (quote (1 . (2 . (3 .())))) 
==> '(1 2 3) 
(cons (quote a) (cons (quote b) (quote c))) 
==> (cons '1 (cons '2 '(3 .()))) 
==> '(1 2 3) 

Cette valeur est imprimée par le REPL comme une liste parce qu'il est une « bonne liste ». Chaque côté droit (cdr) est une liste, tout le chemin jusqu'à la liste vide à la fin, donc cette valeur suit parfaitement la forme de la liste. Le REPL suppose que vous souhaitez voir le résultat sous forme de liste, afin qu'il soit imprimé sans . présent.

Vous verriez '(1 2 . 3) pour (pair-test (1 2 . 3)), parce que c'est ainsi que le REPL imprime des "listes incorrectes". Si le dernier élément de la chaîne de paires n'est pas la liste vide, la valeur est considérée comme une "liste incorrecte" et sera imprimée différemment:

(quote (1 . (2 . 3))) 
==> '(1 2 . 3) 
(cons 1 (cons 2 3)) 
==> '(1 2 . 3) 
Questions connexes