ushidayの日記

主に「IBMi」のメモに・・・

Haskell読書会4th@ShizuDev

早いものでShizuDev主催のHaskell読書会も第四回を迎える事が出来ました。今回はin三島という事で、初の東部開催です。段取りなどは、東部の方に、御協力を頂いた事に感謝しております。場所は三島の商工会議所で、非常に設備も良いところで、ぜひまた使わせて頂きたいと思いました。今回使用した部屋以外にも、ディスカッションやロールプレイングに使えそうな部屋もあり、少数名でディスカッション形式の勉強会も面白いなと思いました。

スピーカーは、静岡IT Proの代表でもある、id:ftnkさんで、第五章のテーマは「リスト内包表記」についてです。締めはシーザー暗号のクラックまでと、一つのテーマなのですが、演習問題は意外と骨の有る章でした。
今回の勉強会で、今までと少し違ったスタイルだったのは、課題図書を読み上げた所までで、出来る演習問題は、こなしてしまうという手法です。過去の勉強会は、最後に纏めて演習問題だったのですが、記憶に焼き付いて間もなく演習問題をする方が、効率も良く、些細な疑問も処理し易かったように思えます。自分の時は、「このスタイルでイコウ」と思いました。

個人的にはループ処理のガチガチ頭の人間からすると、リスト内包表記の妙味というか、そう言ったものを感じ取れました。
例えば、サイコロの出目のパターンをRPGでループ処理した時、
RPGの場合

%subarr(xs:1) ='123456';
%subarr(ys:1) ='123456';
i = 0;
for ix1 = 1 to 6 ;
    for ix2 = 1 to 6 ;
         i+=1;
         ptn(i).x = xs(ix1);
         ptn(i).y = ys(ix2);
    endfor;
endfor;

は、こんな感じで、手続き型言語で見る典型的な例かと思います。次にHaskellのリスト内包表記
Haskellの場合

[(x,y)|x<-[1..6],y<-[1..6]]

ループの入れ子が、ワンライナーで書けてしまうところが、レガシー人間からするとただただ羨ましい。(最初にforeachを見た時も少し感動したぐらいですから)
このリスト内包表記の入れ子は、カンマ区切りでさらに拡張できます。たとえば3つの入れ子ならば、

[(x,y,z)|x<-xs,y<-ys,z<-zs]

となります。さらに抽出条件まで付けてしまう事が出来ます。例えば,x,y,zの合計が20以上のみリストとするみたいな場合

[(x,y,z) | x<-xs,y<-ys,z<-zs,sum([x,y,z]) >=20]
or
[(x,y,z) | x<-xs,y<-ys,z<-zs,(x+y+z) >=20]

実に不思議だと感じたのは、ただカンマ区切りにしただけで、何故にココまで高機能なのか?もちろん実装がそうなるように工夫してあるといえばそうなのだけど、演習問題でリスト内包表記の入れ子が出てきた時に、こう感じました。「これはある意味シンタックスシュガーなのでは?」と...。

前述の以下の表記は、
■例1

[(x,y)|x<-[1..6],y<-[1..6]]
や
[(x,y,z)|x<-[1..6],y<-[1..6],z<-[1..6]]

こう書く事も出来る
■例2

concat [[(x,y)|y<-[1..6]]|x<-[1..6]]
や
concat ( concat [[[(x,y,z)|z<-[1..6]]|y<-[1..6]]|x<-[1..6]] )

リスト内包表記を1つのシンタックスとして捉えた時、通常入れ子を表現する場合、実は例2の方がごく自然な形で、ただ入れ子にすればする程、concatが必要になり、リスト表現としても分かりづらくなる、そこで工夫されたのが、例1の様なシンタックスシュガーなのかと、勝手に理解しました。普通に考えて、例1が使えれば例2は複雑なだけで、通常使う場面がないなと思うほど良く出来ていて、あえてソレを解らせるための演習問題?と考えると奥が深いなと思い知らされました。
色々な意味で、さらにHaskellの世界に引き込まれていく予感が...。

今回のおやつは、メンバー中最年少高校生のSupaki君が、かの遠州銘菓”たこまん”で買ってきてくれました。”たこまん”の名前だけはよく見るのですが、食べるのは初めてで、ブッセ風の美味しいオヤツをありがとう。

■おやつ