2008年1月15日火曜日

Chapter 22 LOOP for Black Belts

LOOPが好きになれるかどうか、が読みどころ。
CLの言語コアよりも上の部分の各種機構って、とどのつまりはミニ言語というかDSLだと思うのですね。ミニ言語やDSL自体を否定していたら、常に言語コアのみで書かないといかんとなってしまう。なので、DOとかはS式っぽいDSLで、拡張LOOPはS式っぽくないということだけだと思うのです。でも何故か、LOOPを見てると不安になるんですよね。それがどこからきてるのか。


前説

特になし。


The Parts of a LOOP

お、さすがに箇条書きをはじめた。この著者が箇条書きにするってことは、LOOPってやっぱりそういうものなんですね。


Iteration Control
Counting Loops
Looping Over Collections and Packages

特になし。


Equals-Then Iteration

この章かなりごつい。。。とにかく例をやってみて理解していくことにする。


CL-USER> (loop repeat 5
for x = 0 then y
for y = 1 then (+ x y)
collect y)
(1 2 4 8 16)
CL-USER> (loop repeat 5
for y = 1 then (+ x y)
for x = 0 then y
collect y)
(1 1 2 4 8)
CL-USER> (loop repeat 5
for x = 0 then y
and y = 1 then (+ x y)
collect y)
(1 1 2 3 5)
CL-USER>

この違いは? ああそうか、どの時点のx,yを参照するかの違いなのか。forの評価はそれぞれ独立して逐次なので、後ろのforの中は前のforの評価結果(今回ループ)を参照可能。andはそれを揃えるときに使うと。


Local Variables

withの例がない。うーむ。
説明を読む限り、補助変数として名前をもった方が記述が楽なときに使用するもの。


Destructing Variables

CL-USER> (defun hoge (list)
(loop for cons on list
do (format t "~a" (car cons))
when (cdr cons) do (format t ", ")))
HOGE
CL-USER> (hoge '(1 2 3 4 5))
1, 2, 3, 4, 5
NIL
CL-USER> (defun piyo (list)
(loop for (item . rest) on list
do (format t "~a" item)
when rest do (format t ", ")))
PIYO
CL-USER> (piyo '(1 2 3 4 5))
1, 2, 3, 4, 5
NIL
CL-USER>

これはたしかにhandy。
読みやすいし、書きやすい。


Value Accumulation

う。なんか便利すぎてくやしい。


Unconditional Execution

-esqueって、〜風とか、〜っぽいって意味なんですね。


Conditional Execution


CL-USER> (loop for i from 1 to 100
if (evenp i)
minimize i into min-even and
maximize i into max-even and
unless (zerop (mod i 4))
sum i into even-not-fours-total
end
and sum i into even-total
else
minimize i into min-odd and
maximize i into max-odd and
when (zerop (mod i 5))
sum i into fives-total
end
and sum i into odd-total
do (format t "~{~a; ~}~%" (list
min-even
max-even
min-odd
max-odd
even-total
odd-total
fives-total
even-not-fours-total)))
0; 0; 1; 1; 0; 1; 0; 0;
2; 2; 1; 1; 2; 1; 0; 2;
2; 2; 1; 3; 2; 4; 0; 2;
2; 4; 1; 3; 6; 4; 0; 2;
2; 4; 1; 5; 6; 9; 5; 2;
2; 6; 1; 5; 12; 9; 5; 8;
2; 6; 1; 7; 12; 16; 5; 8;
2; 8; 1; 7; 20; 16; 5; 8;
...


改造版。さすがにSLIMEの自動インデントは対応してなかった。


Setting Up and Tearing Down

う、Perl難しい。。。


Termination Tests

特になし。


Putting It All Together

特になし。


著者が言っている「繰り返しにはパターンがあり、それはDSL構築に値する」というのはその通りだと思います。あと、通常の英語っぽくすることが、拡張LOOP設計者の狙いだったとのことです。読んでみて、私の整理はこんな感じです。


  • 繰り返しを表現する英語の語彙や構文は、自然言語にしては、なかなかアルゴリズムの表現に適したものであり、
  • だったらそれをそのまま文法にしてDSLをつくるのがいいじゃん。というノリか。それはアリだと思う。
  • これが日本語ではたぶん無理。
  • しかし自然言語の語彙と構文をもってきてるから、そっちの知識も頭にあるので慣れるまではノイズがでる。
  • これが不安感。
  • たぶん、ノイズの度合いは、英語が日常の言語の人と、私のように日本語が日常の言語の人ではずいぶん違うはず。
  • 個人的には繰り返しを再帰で書くのは嫌いではない。
  • しかし、再帰の実戦的なメリットは、繰り返しが書けるということではなくて、関数を宣言的に書けるということの場合が多いと思う。

0 件のコメント: