dsm:ここのコードにはいくつか奇妙な点があります。ご了承ください
(loop for x from 1 to 100000
for y from 1 to 100000 do
collect `(,x . ,y))
次と同等です。
(loop for x from 1 to 100
collecting (cons x x))
これはおそらくあなたが意図したものではありません。3 つのことに注意してください。まず、あなたが書いた方法では、x と y は同じ役割を持っています。おそらく、ループをネストするつもりでした。次に、y の後の do は正しくありません。これは、それに続く lisp フォームがないためです。第三に、ここでバックティック アプローチを使用できることは正しいですが、コードが読みにくくなり、慣用的ではないため、避けるのが最善です。
実際に何を意図したかを推測すると、(ループを使用して) 次のようにすることができます。
(loop for x from 1 to 100 appending
(loop for y from 1 to 100 collecting (cons x y)))
ループ マクロ (Kyle など) が気に入らない場合は、次のような別の反復構造を使用できます。
(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))
この種のことを頻繁に行っていることに気付いた場合は、リストを横断するためのより一般的な関数を作成してから、これらの整数のリストを渡す必要があります。
ループだけでなく、反復に本当に問題がある場合は、この種のことを再帰的に行うことができます (ただし、これはスキームではないことに注意してください。実装によって TCO が保証されない場合があります)。ここでKyle が示した関数「genint」は、一般的な (ただし標準ではない) 関数 iota の変形です。ただし、リストに追加することはお勧めできません。次のような同等の実装:
(defun iota (n &optional (start 0))
(let ((end (+ n start)))
(labels ((next (n)
(when (< n end)
(cons n (next (1+ n))))))
(next start))))
はるかに効率的なはずですが、それでも末尾呼び出しではありません。注: これは、より一般的な 0 ベースに設定しましたが、1 またはその他の整数から開始するオプションのパラメーターを指定しました。もちろん、上記は次のように書くことができます。
(defun iota (n &optional (start 0))
(loop repeat n
for i from start collecting i))
これには、大きな引数に対してスタックを吹き飛ばさないという利点があります。実装がテール コールの削除をサポートしている場合は、次のようにして、再帰が場違いに実行されるのを回避することもできます。
(defun iota (n &optional (start 0))
(labels ((next (i list)
(if (>= i (+ n start))
nil
(next (1+ i) (cons i list)))))
(next start nil)))
それが役立つことを願っています!