2010-11-20 8 views
4

Le code suivant Common Lisp ne produit pas la sortie que je me attends à:Comment la macro "loop for" de Common Lisp fonctionne-t-elle avec plusieurs "et" ed counters?

(loop for a from 5 to 10 
     and b = a do 
     (format t "~d ~d~%" a b)) 

En utilisant SCBL, il produit cette sortie:

5 5 
6 5 
7 6 
8 7 
9 8 
10 9 

Je me attendais les valeurs de a et b être le même sur chaque ligne.

J'ai cherché sur le web une bonne documentation de la macro de boucle dans cette instance mais je n'ai pas trouvé grand-chose. J'apprécierais n'importe quel aperçu!

Répondre

11
(loop for a from 5 to 10 
     and b = a 
     do (format t "~d ~d~%" a b)) 

code ci-dessus peut être vu sur le plan conceptuel près d'un PSETF. Les valeurs sont mises à jour en parallèle. La raison en est l'ET.

Remplaçons ET avec POUR:

(loop for a from 5 to 10 
     for b = a 
     do (format t "~d ~d~%" a b)) 

Au-dessus mettra à jour les variables conceptuellement proches d'une SETF habituelle, « séquentielle ».

CL-USER 20 > (loop for a from 5 to 10 
        for b = a 
        do (format t "~d ~d~%" a b)) 
5 5 
6 6 
7 7 
8 8 
9 9 
10 10 

Pour une explication voir le Common Lisp HyperSpec 6.1.2.1 Iteration Control:

Si plusieurs clauses d'itération sont utilisées pour contrôler l'itération, la variable d'initialisation et pas à pas se produire séquentiellement par défaut. La construction et peut être utilisée pour connecter deux ou plus clauses d'itération lorsque liaison séquentielle et pas à pas sont pas nécessaire. Le comportement d'itération des clauses jointes par et est analogue au comportement de la macro de avec rapport à faire *.

+1

Donne du sens maintenant, merci pour l'explication claire! – presto8

3

Les formes pas à pas des clauses AND sont évaluées avant que l'une des variables ne reçoive ses nouvelles valeurs. Utilisez plutôt for b = a then a pour forcer l'évaluation dans l'ordre.

Réf. http://www.gigamonkeys.com/book/loop-for-black-belts.html#equals-then-iteration

+0

Merci pour la réponse! J'ai essayé "pour b = a puis un" et il a produit la même sortie, malheureusement. – presto8

+0

@ presto8 Eh bien, ça marche pour moi, c'est tout ce que je peux dire. –

+0

Intéressant. J'ai essayé "un puis un" sur SBCL et LispWorks et il a eu les mêmes résultats. Eh bien, merci quand même! – presto8