LOOP マクロのコツ
LOOP マクロを使うとき、わたしはつい、以下のように書いてしまう。
(defun parse-grid (grid) "テキスト形式 grid を可能な値のハッシュテーブルに変換する。 square => digits ただし矛盾が見つかった場合は nil を返す。" (let ((values (make-hash-table))) (loop for s in squares do (setf (gethash s values) digits)) (loop for s being the hash-keys in (grid-values grid) using (hash-value d) if (and (member d digits) (not (assign values s d))) do (return nil) finally (return values))))
この形は、let の中に loop が書いてある。これだと関数の本体は、let 式だ。こうではなく、LOOP が関数の本体になるように書くと、下のようにより簡潔になって、良いと思う。
(defun parse-grid (grid) "テキスト形式 grid を可能な値のハッシュテーブルに変換する。 square => digits ただし矛盾が見つかった場合は nil を返す。" (loop with values = (make-hash-table) initially (loop for s in squares do (setf (gethash s values) digits)) for s being the hash-keys in (grid-values grid) using (hash-value d) never (and (member d digits) (not (assign values s d))) finally (return values)))
ここでは with を使ってローカル変数を定義し、さらに initially を使って前処理を行っている。また return を一つ減らして、never を使うようにもした。