dsm: il y a deux ou trois choses bizarres à propos de votre code here. Notez que
(loop for x from 1 to 100000
for y from 1 to 100000 do
collect `(,x . ,y))
équivaut à:
(loop for x from 1 to 100
collecting (cons x x))
qui est probablement pas tout à fait ce que vous vouliez. Notez trois choses: Premièrement, comme vous l'avez écrit, x et y ont le même rôle. Vous avez probablement voulu nicher des boucles. Deuxièmement, votre faire après le y est incorrect, car il n'y a pas de forme lisp qui le suit. Troisièmement, vous avez raison de dire que vous pouvez utiliser l'approche backtick ici, mais cela rend votre code plus difficile à lire et n'est pas idiomatique pour aucun gain, donc mieux vaut l'éviter.
Deviner ce que vous avez réellement l'intention, vous pourriez faire quelque chose comme ça (boucle en utilisant):
(loop for x from 1 to 100 appending
(loop for y from 1 to 100 collecting (cons x y)))
Si vous n'aimez pas la macro boucle (comme Kyle), vous pouvez utiliser une autre itération construire comme
(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))
Si vous vous trouvez faire ce genre de chose beaucoup, vous devriez probablement écrire une fonction plus générale pour les listes de traverser, passer ensuite ces listes d'entiers
Si vous avez vraiment un problème avec l'itération, pas seulement en boucle, vous pouvez faire ce genre de chose récursivement (mais notez que ce n'est pas un schéma, votre implémentation peut ne pas garantir le TCO). La fonction "genint" montrée par Kyle here est une variante d'une fonction commune (mais pas standard) iota.Cependant, l'ajout à la liste est une mauvaise idée. Une implémentation équivalente comme ceci:
(defun iota (n &optional (start 0))
(let ((end (+ n start)))
(labels ((next (n)
(when (< n end)
(cons n (next (1+ n))))))
(next start))))
devrait être beaucoup plus efficace, mais n'est toujours pas un appel de queue. Note J'ai configuré ceci pour la base 0 la plus habituelle, mais vous donne un paramètre optionnel pour commencer à 1 ou tout autre entier. Bien sûr, le ci-dessus peut être écrit quelque chose comme:
(defun iota (n &optional (start 0))
(loop repeat n
for i from start collecting i))
qui a l'avantage de ne pas souffler la pile pour les grands arguments. Si votre implémentation prend en charge l'élimination des appels de queue, vous pouvez également éviter la récursion en cours d'exécution sur place en faisant quelque chose comme ceci:
(defun iota (n &optional (start 0))
(labels ((next (i list)
(if (>= i (+ n start))
nil
(next (1+ i) (cons i list)))))
(next start nil)))
Hope that helps!
FYI, il suffit de laisser de côté le DO et son ANSI CL conforme. :) (DO est pour l'exécution des expressions Lisp, pas pour l'introduction de clauses LOOP.) –
Merci pour la correction – dsm
Vous êtes sûr de l'avoir fait? Je l'ai couru avec les deux boucles de 0 à 5 et j'ai obtenu ((0. 0) (1 .1) (2 .2) (3. 3) (4. 4) (5. 5)), ce que je ne fais pas. pense était le résultat souhaité. –