Ist es richtig, die Graviszeichen / Komma Idiom in einer verwenden (Schleife ...)?
Frage
Ich habe einige Codes, die Punkte (Consed ganze Zahlen) von einer Schleife sammelt, die etwa wie folgt aussieht:
(loop
for x from 1 to 100
for y from 100 downto 1
collect `(,x . ,y))
Meine Frage ist, ist es richtig, `(,x . ,y)
in dieser Situation zu benutzen?
Edit: Diese Probe ist nicht über eine Tabelle von 100x100 Elementen zu erzeugen, hier der Code illustriert nur die Verwendung von zwei Schleifenvariablen und die consing ihrer Werte. Ich habe die Schleife bearbeitet, um dies deutlich zu machen. Die eigentliche Schleife I hängt Verwendung von mehreren anderen Funktionen (und ist ein Teil von einer selbst), so dass es sinnvoller, die Anrufe mit wörtlichen ganzen Zahlen zu ersetzen und die Schleife aus der Funktion zu ziehen.
Lösung
Es wäre viel 'besser' sein zu tun (cons x y).
Aber die Frage beantworten, , es ist nichts falsch mit, dass :) tun (außer es macht ein bisschen langsamer).
Andere Tipps
Ich denke, die Antwort hier Ressourcennutzung ist (nach von Dieser Beitrag )
zum Beispiel in clisp:
[1]> (time
(progn
(loop
for x from 1 to 100000
for y from 1 to 100000 do
collect (cons x y))
()))
WARNING: LOOP: missing forms after DO: permitted by CLtL2, forbidden by ANSI
CL.
Real time: 0.469 sec.
Run time: 0.468 sec.
Space: 1609084 Bytes
GC: 1, GC time: 0.015 sec.
NIL
[2]> (time
(progn
(loop
for x from 1 to 100000
for y from 1 to 100000 do
collect `(,x . ,y)) ;`
()))
WARNING: LOOP: missing forms after DO: permitted by CLtL2, forbidden by ANSI
CL.
Real time: 0.969 sec.
Run time: 0.969 sec.
Space: 10409084 Bytes
GC: 15, GC time: 0.172 sec.
NIL
[3]>
dsm: Es gibt ein paar seltsame Dinge über Ihren Code hier . Beachten Sie, dass
(loop for x from 1 to 100000
for y from 1 to 100000 do
collect `(,x . ,y))
entspricht:
(loop for x from 1 to 100
collecting (cons x x))
das ist wahrscheinlich auch nicht ganz das, was Sie bestimmt. Beachten Sie drei Dinge: Erstens, wie Sie es geschrieben haben, x und y die gleiche Rolle haben. Sie haben wahrscheinlich zu nisten Schleifen gemeint. Zweitens Ihre do nach dem y ist falsch, da es nicht lispeln Form es finden. Drittens sind Sie richtig, dass Sie hier den Graviszeichen Ansatz verwenden könnten, aber es macht den Code schwerer zu lesen und nicht idiomatische für keinen Gewinn, so am besten vermieden werden.
Erraten, was Sie eigentlich gedacht, man könnte so etwas wie diese (mit Schleife) tun:
(loop for x from 1 to 100 appending
(loop for y from 1 to 100 collecting (cons x y)))
Wenn Sie nicht über die Schleife Makro mögen (wie Kyle), können Sie eine weitere Iteration konstruieren wie
verwenden(let ((list nil))
(dotimes (n 100) ;; 0 based count, you will have to add 1 to get 1 .. 100
(dotimes (m 100)
(push (cons n m) list)))
(nreverse list))
Wenn Sie sich selbst tun, diese Art der Sache viel zu finden, sollten Sie vielleicht eine allgemeinere Funktion für die Überquerung Listen schreiben, dann geben sie diese Listen von ganzen Zahlen
Wenn Sie wirklich ein Problem mit Iteration haben, nicht nur Schleife, können Sie diese Art der Sache tun rekursiv (aber beachten Sie, dass dies nicht Schema, Ihre Implementierung kann TCO nicht garantiert). Die Funktion "genint" gezeigt von Kyle
Warum nicht einfach By the way, habe ich versucht, den Code in CLISP zu laufen und es nicht wie erwartet. Da ich hier kein großer Fan der Schleife Makro bin, wie Sie das Gleiche erreichen könnte rekursiv: (cons x y)
(defun genint (stop)
(if (= stop 1) '(1)
(append (genint (- stop 1)) (list stop))))
(defun genpairs (x y)
(let ((row (mapcar #'(lambda (y)
(cons x y))
(genint y))))
(if (= x 0) row
(append (genpairs (- x 1) y)
row))))
(genpairs 100 100)