実践Common lispを読み始めた-第22章 黒帯のためのLoop

繰り返し構文を書くための言語らしい。
マクロがDSL(Domain Specific Language)を作るためにあるというのをLispセミナーのときに講師の黒田さんがおっしゃっていたが、Loopもその一例なのかもしれない。

Loopでできること

  • ループしている間にCollect, Count, Sum, Minimize, Maximaizeする。Collectというのは収集したものを要素としたListを作ることと思っていいのかな。Count, SumはともかくとしてMinimize, Maximizeというのは最小値と最大値をとるということなのか?最小化、最大化と日本語でかかれていてもよくわからない。
  • 任意のLisp式を実行できる。
  • ループの終了条件を決定
  • 条件付きで実行

これらに加えて、

  • ループ内で使用するローカル変数の生成
  • ループの前後に実行する任意のLisp式の実現。

なのだそうだ。

反復の制御

forかasを使う。

数えるループ

  • from, downfrom, upfrom
  • to, upto, below, downto, above

コレクションやパッケージについてループする

  • for節にin, onを使う
(loop for i in (list 1 2 3 4) collect i);リスト要素から一つ一つ全部とりだす。

=とthenによる反復

一気にAlgol風な感じ

ローカル変数

withを使う

変数を分配する

CL-USER> (loop for (a b c) in '((1 2 3) (4 5 (6 7)) (8 9))
	      do (format t "a: ~a; b: ~a; c: ~a~%" a b c))
a: 1; b: 2; c: 3
a: 4; b: 5; c: (6 7)
a: 8; b: 9; c: NIL
NIL

値の累積

動詞 機能
collect 取り出した値を要素としたリストを作る
append リストに追加する
nconc 破壊的なappend
count
sum 合計
maximize 最大値
minimize 最小値

無条件実行

ループの中で、collectとかmaximizeとか決まった処理じゃなくて、任意のことをしたい場合。do節を使う。

(loop for i from 1 to 100 do (print 1))

条件実行

無条件実行を説明したら当然、条件実行も知りたくなる。
ポイントは、

  • do節を使う場合はその先で条件分岐を書いてしまえばOK。
  • 累積節を条件実行したい場合はdo節を使えないので、loopに用意されている条件構文を使う
  • 条件構文はif, when, unlessの3つがある。ifとwhenの振る舞いは同じ。
CL-USER> (defparameter *alist* '(tokyo osaka kyoto yokohama)) ;都市名のリスト
*ALIST*
CL-USER> (defparameter *ahash* (make-hash-table)) ;hash tableを作る
*AHASH*
CL-USER> (setf (gethash 'osaka *ahash*) 'kansai-international-airport) ;hashに都市名に対応する国際空港をセット
KANSAI-INTERNATIONAL-AIRPORT
CL-USER> (setf (gethash 'tokyo *ahash*) 'narita-international-airport) ;東京と大阪はあるけど、京都と横浜には同一府県にない。(実は東京も違うけど成田ということしておく)
NARITA-INTERNATIONAL-AIRPORT
CL-USER> (loop for key in *alist* when (gethash key *ahash*) collect key) ;空港がある都市だけを表示
(TOKYO OSAKA)
CL-USER>