第三回Haskell読書会
第三回Haskell読書会が静岡市民文化会館で、開催され無事終了致しました。
スピーカーのid:kynbitさん、高校生という若さでLTをしてくれたSupakiくん、関係者並びにご参加頂いた皆様ありがとうございました。
ついつい話が脱線しがちな中、kynbitさん曰く、「今回の第四章のテーマは、あくまでも”関数の定義する方法を学ぶ”」という、かの名言で直ぐに軌道修正。前回よりも会場利用時間が、30分短いという中、ハンズオンを中心にまとめて頂き、充実していたのではと思います。
関連ブログ
本章の内容については、参加メンバーが既に、ブログで書かれているので、そちらで雰囲気を感じて頂けたらと。
おやつ
2開催連続で、代表のたかはしさんが、タマゴ型プリン&たまごボーロを、仕入れてきてくれました。ありがとうございます。そしてウマイ!頭使って糖分補給コレ基本です。たまごボーロも懐かしいです。口の中の水分みんな持っていかれる感じが何とも言えない。
(「eatたまごボーロ :: たまごボーロ → 口の中砂漠化」「drinkお茶 :: お茶 → 口の中オアシス」)
SupakiくんLT
最年少のSupaki君が、TwitterをテーマにLTをやってくれました。
Twitterのキモは”おやじギャグなんだ!”と教わりました。高校生にして、アラサーやアラフォーのオッサン相手に、OpenOfficeでスライド作るなんてすごい経験だよ。将来有望です。
練習問題1を2次会で「あーだこーだ」
本章の練習問題1は以下の様な内容でした。
要素数が偶数のリストを引数にとる関数「halve」は、要素数の真ん中で2分割したリストのタプルを返す。 つまり... halve [1,2,3,4,5,6] >([1,2,3],[4,5,6]) になれば良いと
kynbitさんから、追加の課題で「奇数の時は、リストを返さないでエラーを...」。しかし終了時間を迎え、急いで片付け、そのまま懇親会へ。そして2次会で、「奇数でエラーって型宣言しているから、空リストのタプル返すくらい?」みたいな話で、「まぁ、それだけでもやってみようYo!」とバーでPC引っ張り出してきて「あーだこーだ」。(何やってんだろ?)
Haskellとしては(関数型としては?)、当たり前の事が、やはりいざキーボード叩いてみると、上手くいかなかったり、面白い発見もあったり、とりあえずの結論が出たところで、2次会は解散。そんな中で、where節を改めて考えてみました。
バーで追加課題をやっていた時、まずこういう書き方で、Parseエラー
-- parse error on input `|' halveBar::[a]->([a],[a]) halveBar xs | (length xs `mod` 2) == 0 = (take (myLen) xs ,drop (myLen) xs) where myLen = length xs `div` 2 | otherwise = ([],[])
で
halveBar::[a]->([a],[a]) halveBar xs | (length xs `mod` 2) == 0 = (take (myLen) xs ,drop (myLen) xs) | otherwise = ([],[]) where myLen = length xs `div` 2
こっちはOK。where節を細かくやっていないので、自分が語ると間違っていそうで、アレなのですが、調べてみると...。
-
- where節は、直前の束縛の右辺に対して作用する。
- where節は、直前の束縛より深いインデントでなければならない。
確かにガードは、「if then else if then else ...〜」のシンタックスシュガーみたいなモノだから、前の例だとthenとelseの間にイキナリwhereを入れている様なもので、よくよく考えればおかしい。つまりこうしているのと同じ
halveBar::[a]->([a],[a]) halveBar xs = if (length xs `mod` 2) == 0 then (take (myLen) xs ,drop (myLen) xs) where myLen = length xs `div` 2 -- if ならせんヤロ else ([],[])
halveBarの束縛に対して、whereで局所定義するなら、普通にこうなる。
halveBar::[a]->([a],[a]) halveBar xs = if (length xs `mod` 2) == 0 then (take (myLen) xs ,drop (myLen) xs) else ([],[]) where myLen = length xs `div` 2
ifだと間違えない、それはそんな処にwhere入れたら、違和感を感じるから。でもガードみたいな見慣れない、シンタックスを拝んだりすると、変な錯覚をしてしまい、違和感を感じない。(そもそもガードの書き方に違和感を感じたり。見やすくて好きなんですけどね、^_^ガード。自分ガード派です。今のところ...)あーダメな自分を再認識しました。そして理解した上でまとめ。
halve::[a]->([a],[a]) halve xs | myEven = (take myHalfLen xs ,drop myHalfLen xs) | otherwise = ([],[]) where myLen = length xs --リストの長さ myHalfLen = myLen `div` 2 --リストの半分の長さ myEven | (myLen `mod` 2 ) == 0 = True --要素数の偶数判定 | otherwise = False
whereは直前の束縛の右辺に対して作用とあるが、上の記述は正しく動いているので、同一where内の束縛に対しても有効みたい。(myLenはmyEvenなどでもスコープ出来ているので...。)これは、結果論なので、本当に正しいのかはチト不安な気もします。
スコープでダメな例は以下のような場合。
-- Not in scope: `myHalf' -- Failed, modules loaded: none. halveNG::[a]->([a],[a]) halveNG xs | myEven = (take myHalfLen xs ,drop myHalfLen xs) | otherwise = ([],[]) where myLen = length xs myHalfLen = myLen `div` myHalf -- myHalfはスコープできない。 myEven | (myLen `mod` myHalf ) == 0 = True | otherwise = False where myHalf = 2
この場合は、それぞれwhere節が下のように、必要になる。
halveNG::[a]->([a],[a]) halveNG xs | myEven = (take myHalfLen xs ,drop myHalfLen xs) | otherwise = ([],[]) where myLen = length xs myHalfLen = myLen `div` myHalf where myHalf = 2 myEven | (myLen `mod` myHalf ) == 0 = True | otherwise = False where myHalf = 2
今回はひょんなことから、where節の理解が少し深まりました。次回の第4回は三島で行うことに決定しました。また正式に決まり次第告知させて頂きます。
2010.7.24(土)のグランシップ開催だけは、リアルガンダム東静岡に初お披露目とあって、早速会場をキープしました。;-)