LOOP マクロでできないこと
残念ながら Common Lisp の LOOP マクロでもできないことがあるようだ。「あらゆる数独パズルを解く」の python のコードで、search という関数で見つけた。
def search(values): "深さ優先探索と制約伝播を使い、すべての可能なvaluesを試す。" if values is False: return False ## 前の時点で失敗している if all(len(values[s]) == 1 for s in squares): return values ## 解けた! ## 取り得る値の個数が最小である未確定のマスsを選ぶ n,s = min((len(values[s]), s) for s in squares if len(values[s]) > 1) return some(search(assign(values.copy(), s, d)) for d in values[s])
search 関数の下から3行目で、辞書の要素の長さが最小となる辞書のキー s とその長さ n(値としては捨てている) を一行で取得している。LOOP マクロには minimizing というのがあるが、これを使っても値しか取れない。調べたところ LOOP マクロではなく ITERATE マクロというのを使うとできるようだ。以下の例は、リストの長さを最大にする要素を取り出している。
;; http://items.sjbach.com/211/comparing-loop-and-iterate の *Finding* より (iter (for lst in '((a) (b c d) (e f))) (finding lst maximizing (length lst))) => (B C D) ;; The rough equivalent in LOOP: (loop with max-lst = nil with max-key = 0 for lst in '((a) (b c d) (e f)) for key = (length lst) do (when (> key max-key) (setf max-lst lst max-key key)) finally (return max-lst)) => (B C D)