loop - lisp-cookbook-ja/common-lisp GitHub Wiki

制御構造

繰り返し(loop)

無限ループ

loopキーワードをなにも指定しなければ無限ループです。

(loop (print "hello")
      (print (random 100)))
;-> "hello" 
    49 
    "hello" 
    37
    ... 

シーケンス上でのループ

forキーワードでループ変数を宣言できます。 続けて in でリスト上を across でベクタ上を渡り歩きます。 ハッシュテーブルには being hash-keys of または being hash-values of を使います。

;; 奇数の要素のみ取り出して、その二乗した値をリストにして返します。
(loop for i in '(1 2 3 4 5) if (oddp i) collect (* i i))
;=> (1 9 25)

;; 文字コードが奇数の文字のみ取り出してリストにして返します。
(loop for i across "hello" if (oddp (char-code i)) collect i)
;=> (#\e #\o)

;; ハッシュテーブルを渡り歩きます。順序は定義されていません。
(loop for i being the hash-keys of (make-hash-table)
      do (print i))
;; キーだけでなく値も参照したい場合は using で指定します。
(loop for i being the hash-keys of (make-hash-table)
      using (hash-value j)
      do (print (cons i j)))

複数のforを指定できますが、入れ子になるのではなく並列して処理されます。 最初に終端にきたところでループは終わります。

(loop for i in '(1 2 3)
      for j in '(4 5)
      do (print (cons i j)))
;-> (1 . 4) 
    (2 . 5)
;=> NIL

補助変数の導入

withキーワードでループ内変数を宣言できます。 初期値を指定しない場合はnilになります。 forと違い値は勝手に更新されません。

(loop with x = 1
      with y
      repeat 3
      do (setf y x)
         (print y))

ループ変数の型指定

of-type キーワードでループ変数の型を指定できます。 コンパイラが優秀であれば効率の良いコード生成の助けになるでしょう。

;; i の型を fixnum と宣言します。
(loop for i of-type fixnum from 0 to 10 do (print i))