2015/06/22

FoldLeft

FoldLeftという考え方について。
(関数型プログラミングについて初学者が錯綜しているので話半分で)

例によって1から9までの数字を足した結果を求めよ、というプログラムの話になるんだけど
とあるScala講義(どこかの大学かな)でこんな話をしていた。

■この教室にいる人全員の年齢を足した結果を求めたい

一つのやり方は、まず1枚の紙を用意して端の人に渡す。その人は年齢を書いて次の人に渡す。
次の人は紙の数字を、自分の年齢を足した数に書き直して、また次の人に渡す。(鉛筆と消しゴムを使うんだろう)。
これを終わりの人まで繰り返す。最後の人は紙を教師に渡して完成。
このやり方は、totalという変数を用意し、forループ内でどんどん数を足していく従来のプログラミングとおんなじだ。

もう一つのやり方は、(全員が紙を持ってるとして)最初の人は自分の年齢を書いた紙を次の人に渡す。
次の人はその数と自分の年齢を足した数を別の紙に書いて次の人に渡す。 これを終わりまで繰り返す。
これで完成で良いんだけど、より正確には最後の人は自分の年齢を足した数を書いた紙を前の人に戻す。今度はどんどん前の人に戻して最初の人まで戻ったら教師に渡すというやり方にする(ちょうど最後の人は教室の後ろの席だとすればなんとなくわかる)。
どんどん新しい紙にするという部分が最初のやり方と違う。
プログラミングで考えると、totalという変数に当たるものが無い。
最初の人から最後の人まで繰り返すという言葉に反して、このやり方をループで書くのはしんどい(紙を変数に見立てた場合)。

これを再現するのが関数型の書き方で再帰を使った書き方になる。以下はJavaScriptでの実装例(だと思う)。

var list = [1,2,3,4,5,6,7,8,9]

var f = function(val, list){
  if (list.length === 0) {
    return val
  } else { 
    var e = val + list.shift()
    return f(e, list) 
  }
}
console.log(f(0, list)) 

うーん、ちょっと何やってるか分かんないと思う。どうせうまく説明できないが説明すると、fという関数は初期値0と数値のリストを渡される。
1. リストが空なら第一引数のvalをそのまま返す。
2. リスト内に数値があれば先頭の数を足し、その数と残りのリストでもう一度fを呼び出す。
3. 残りのリスト内にまだ数値があれば先頭の数を足して、その数と残りのリストでまたfを呼び出す。
...
x. 最後まで行くと全部足した数と空のリストでfが呼び出されるので、全部足した数が返される。
再帰なので最後まで行くと一気に最初の関数呼び出しのとこまで戻されることになる。

list.shift() というのが微妙なとこだ。
リストの先頭の要素を取り出す関数だが、取り出すと本当にリストから削除される、popのような関数だ(popは後入れ先出しなのでそこが異なる、どっちかというとQueueかな?)。
var e = val + list.shift() だけで先頭要素と足し合わせるのと、先頭を除いた残りのリスト、というのをやっている。
これなら順次新しい紙を用意して足し算し、次の人(残りの人)に渡すというようなやり方に沿ったプログラムになってると思う。

この順々にやる方法がFoldLeftという考え方だ(もしかしてFoldRightかも)。
リスト先頭の要素と、何の処理をするか(今回は足し算)と、リストの残りは再帰でやる、という戦略。

せっかくなので全部書こうと思う。
何の処理をするか、というfunctionをfに渡すように作ると汎用的になる。また、リストの先頭要素と残りのリストをそれぞれ分かりやすくlist_headとlist_tailとした。
var list = [1,2,3,4,5,6,7,8,9]

var f = function(val, list, f2) {
  if (list.length === 0) {
    return val
  } else { 
    var list_head = list[0]
    var list_tail = list.slice(1)
    var e = f2(val, list_head)
    return f(e, list_tail, f2) 
  }
}

var plus = function(a,b) {
  return a+b
}

console.log(f(0, list, plus))
となる。リスト内の要素を全部掛け合わせた結果が欲しいなら、
var product = function(a,b) {
  return a*b
}

console.log(f(1, list, product))
となる(最初の値は1に変わる)。
この辺まで考えると、リスト内の数値を全部足した結果を返す、全部掛けた結果を返す、という専用の関数を作りたくなるはず。
var f = function(val, list, f2) {
  if (list.length === 0) {
    return val
  } else { 
    var list_head = list[0]
    var list_tail = list.slice(1)
    var e = f2(val, list_head)
    return f(e, list_tail, f2) 
  }
}

var plus_all = function(list) {
  var plus = function(a,b) {
    return a+b
  }
  return f(0, list, plus)
}

var product_all = function(list) {
  var product = function(a,b) {
    return a*b
  }
  return f(1, list, product)
}

var list = [1,2,3,4,5,6,7,8,9]
console.log(plus_all(list))
console.log(product_all(list))
FireBug等で動くのが分かるだろう。関数型プログラミングになってるはずだ。どんなもんだろう。
plus とか product が関数の中で定義されてるのがちょっとこざかしい感じがする。

関係ないが今年度の新人研修に関わることになって、プログラム言語研修に何の言語を使うかが議論となった。今まではC言語だったのが、Cは古い、もっとプログラミングそのものを教えるのに適した言語があるんじゃないか、という話になり、JavaScriptで研修を行うことになった。
その方針だけ決めて講師は社内のエンジニアを適当にアサインしたのだが、どうも比較演算子には「==」と「===」があるとか、「1 === "1"」はFalseだが「1 == "1"」はTrueになるという内容を教えたらしい。また、JavaScriptには型が無く、数値の足し算のつもりが文字列の連結になるぞ、というようなことを教えたらしい…。
JavaScirptを選択した主旨が伝わってないじゃん。そんな言語仕様ばっかり教えるならCを教えた方がまだ良かったんではないかと。
JavaScriptを教えたいんじゃなく、プログラミングを教えたいだけだったんだけどな。

純粋にプログラムを教えるために余計な言語仕様にとらわれない言語としてJavaScriptって個人的には悪くないと思った。BestとかExcellentではないけどCやJavaと比べれば、Not badと思ったんだけどな。でも初心者を打ちのめすのに効果絶大な言語仕様も多いから、講師のセンスだな。
手続き型としてはコールバックが多用されるのが難しいというのはあると思う。

2015/06/02

ise

伊勢参り感想

金曜に休みを取って金土日と伊勢に行ってきた。
伊勢というか、名古屋、伊勢、二見浦、かな。名古屋観光は新幹線が高額なこと以外は簡単に行き来できるのでいい気分転換になりそう。
名古屋駅から名古屋城まで歩くと結構疲れる。スーツケースはロッカーに預けとこう。
途中で自社の名古屋事業所を外から眺めてみる。まぁ社員証も無いし知り合いもいないと思うので見るだけ。
名古屋城は入るのにお金取る。以前に中入ってみたがそれほど面白くなかったので外側だけ見て帰りの手段を探す。

名古屋城前のバス停に名古屋メーグルというふざけた名前のバスが来てた。名古屋駅も行くようなのでよく確認せずに飛び乗る。しかし名古屋駅から離れる方向のに乗ってしまい、ぐるっと回って名古屋駅まで行くのに1時間ほどかかることが判明。名古屋城から名古屋駅、という方向のメーグルもあるので乗るときは確認するといい。
メーグルは名古屋の観光名所がバス停になってるので降りずに1時間乗るのも楽しいかもしれないし、1日パスで観光地巡りも出来るようになっている。しかし待ち合わせの時間が近いので地下鉄ですぐ名古屋駅に戻れる名古屋テレビ塔で降りた。名古屋テレビ塔の地下街をぐるっと歩く。
札幌の大通りのテレビ搭と似ていて良い。就活のときに一度来たのを思い出した。

名古屋から伊勢市へ

なんと近鉄線で1時間半以上、かかるという。で普通の通勤電車の帰宅ラッシュに当たった模様。1時間くらい混雑したなかで立っていて辛かった。
しかし地元の人に混じって移動をすると旅情を感じる。その前の名古屋テレビ塔から名古屋駅までなどの移動でも、地元の高校生を見たりした。そして彼らは自分とは全く関わらない世界軸に生きてるんだろうなぁなどと思いをはせる。
彼らにとっては何でもない毎日繰り返される日常なのだろうが私にとっては一生のうちでそう何度も無いであろう名古屋旅行の一部分なのだ。
宗教観、輪廻と旅情、何千年と続くこの広い地球上、何百億といた人間の中で、たとえばスクランブル交差点で一瞬すれ違うだけという人であってもすごく強い縁で繋がっている、などと美輪明宏は言っていたっけ。袖振り合うも多生の縁?
まぁそんなことを思ったり思わなかったり。
で、伊勢市へ着く。
日本で最も有名な神社がある街としてはあまりに人が少なく静かだった。金曜だからこんなに静かだが明日は街中参拝客で溢れるはずだ、などと話をする。
その夜はその土地の居酒屋で何故かもつ鍋を食べる。うまかったけど。
泊まったホテル、というかウィークリーマンションには蚊がいた。刺されたかどうかは謎、かゆいのは間違いないがもう布団のせいでかゆいのか、蚊に刺されたのかわかんない。

伊勢神宮参り

伊勢市駅にもロッカーがあるし、駅近くに参拝者向けのお荷物預かり所もあるので旅行鞄は預けて行く。
せっかくなのでと正式なお参り順序で行く。外宮(げくう)までまず歩いてお参りする。
しかしなんと財布には小銭が1円玉一枚しかなかった。途中の自販機で脱水防止にお茶を買ったのだが、そのとき「お、丁度160円あるぞ」などと思って小銭を一掃してしまったのだ。
仕方ないので途中の神社はお辞儀だけして、一番奥の本殿に1円玉をコロンと投げ落とす。外宮とは言えさすがに多くの参拝客がいた。
でバスに乗り内宮(ないくう)へ。バスの中でちゃんと両替して10円玉を量産する。
内宮の前に猿田彦神社へ寄ってお参り。猿田彦神社から内宮は歩いてすぐのようだ。
内宮の前には”おかげ横丁”というお土産屋の通りがある。
これが古い建物の雰囲気を残していてゆっくり回りたくなるのだ。まぁお参りの後で回るとして、内宮の中へ。
本殿に向かう途中に何本も杉の木が生えていたが、一本ずつ全部が御神木のような立派な木だった。
とにかく大きな森の中に大きな神社がある、という感じ。神社もそうだがその土地全部がなんかありがたい雰囲気。そして外宮とは比べ物にならないくらいたくさん人がいた。
まぁ実は神社よりおかげ横丁の方が面白くて人を寄せ付けてそうなんだけど。。
その中の赤福本店で赤福を食べた。うまい。
お土産屋も様々な種類があり、食べ物屋も松阪牛だの伊勢うどんだのあり、良い。
いちいち建物が古い雰囲気だし。そしてたくさんの観光客の中、燕もたくさん飛び回っており、あちこちに燕の巣があった。燕には二見浦でも驚かされる。
さて伊勢神宮には人や燕が沢山いたが、実は蚊も沢山いたようだ。。この日6箇所も刺された。そしてなかなかの毒性の強さ。白黒のやつじゃないから大丈夫かと思ったが。ダメな痒さだった。

二見浦へ

伊勢参りの後二見浦へ移動。ちょっと良い宿というのに泊まる。古い和風旅館だが清潔感もあり、人も少なく、たしかに良い雰囲気。正直二見浦には何もないんだが、それもまた良い。
なんかぼーーーっと過ごす。
ふらっと海岸線を歩き、その土地の名物という塩羊羹の本店に行った。すっごい古いお店で、店内に燕の巣があった。燕の子が5匹並んでうごめいてる姿は若干気持ち悪かったが(蓮の実的なキモさ・・)、燕の巣があるんですねーすごいですねーなどと愛想を言う。でそこで塩羊羹を一本買う。おまけでカエルの小さな置物を貰ってしまった。

翌日、夫婦岩?というのを見学し、伊勢から無事に帰れるようにという古人の願いのこもったカエルの置物を眺めて歩く。そこらじゅうカエルの置物だらけ。
これだけ神社参りをしてるのに、おみくじを一個も買ってないので最後に夫婦岩のところの神社で”カエルみくじ”というのを引いてみる。カエルの口に手を突っ込んでゲコゲコと呟きつつ口の中一番奥のおみくじを引っ張り出す。で、「吉」という普通のやつ。いっつもこれだ。
そういえば夫婦岩はすごく風が強くておみくじ飛ばされそうだなーなどと思っていると、なんと千円札が何枚か飛んできた。それを追いかけるおばちゃんも走ってきた。で千円札が風に乗って3枚とも僕の手元に。もちろんおばちゃんに返したが、もしやあれは金運Upだったのか?
金運といえば夫婦岩の近くには非常に商魂たくましいお土産屋があるので注意が必要だ。必死過ぎてちょっと怖い。二見シーパラダイスというお土産屋ショップの店員もけっこう怖いくらい売り込んでくる。
今後二見浦へ観光に行く人へのアドバイスだが、もしお土産屋の店員が少しでも怖いと思ったら無言で逃げていいと思う。追いかけては来ないので。

帰りは二見浦から名古屋、名古屋から東京、とどんどん都会になっていく。 カエルのご利益か、なにも問題なく帰れた。
実はカエルなんか拝まなくとも無事に帰れただろうが、もしかしたらカエルを拝まなかったら無事では済まなかったかもしれない。それは分からない。こうやって信仰心が芽生えるのは危険だ。カエルを拝んだから無事に帰れた。カエルを拝んでも無事に帰れなかったとしたら信仰心が足りなかったからだ。などとなる。
こういう信仰心、ジンクスが芽生えそうな危険を感じたらあえて崩してみることが必要だ。カエルの置物を蹴っ飛ばして、ちゃんと帰り着く、とかね。
まぁカエルがかわいそうだからそんなことしないけど。

motion sickness

何故か名古屋に向かっている新幹線の中で、新しいモバイルノーパちゃんを持ち出して、華麗にプログラミングでも、と思ったが。
自分は特に乗り物に弱いとは思わないんだけど、PCつけて作業はヤバい。
東京で乗り込み、品川を超えたあたりですでにちょっと乗り物酔い。
ちなみに新幹線の中でネットが繋がるのはU-mobileの格安Simを刺したL-01eでテザリングしているからだ。なんか新幹線もWiFiがあったような話を聞いたような気がしなくもない。しかしよくわからんのでいつも通りスマホのテザーを使う。L-01eにU-mobileを刺してテザリングするためにはroot化して内部設定を変えないといけない。前に四苦八苦してやったがすでにやり方を忘れてしまっている。
新横浜でグロッキー。。

2015/05/23

Wired Wireless

無線LANルーターが壊れかけてた。
どうも最近回線速度が遅いなとは思ってたが、明らかに異常に遅くなり、じゃぁルーターを再起動しようかなと思って手に取ったらほんのり暖かい。
外側はほんのり暖かいくらいだったんだけどもしかしたら熱暴走かなと思ってドライヤーの冷風モードでスリットから風を吹き込んでみた。冷やせば治るかなと。
するとルーターから香ばしい?焦げ臭い?匂いが漂ってきた…。
おそらく8年以上使ってたはずなので買い替えるいい機会だろう。

で、またしてもヨドバシで散々迷った。IEEE802.11nまでの安いモデルか、11acが使える高い奴にするか。
7年前のVaioには11acなんて無いんだけど、新しいモバイルノーパは11ac使えるし、せっかくネットワークに詳しくなったので11acの使えるやつを買ってやった。一回お酒をがまんすればいいくらいの差額だし。むしろ一人酒やめろだし。

ネットワーク詳しくなるとルーターを設定するだけで結構楽しめるもんだ。ルーターのログが見えるんだけど、DHCP関連のログが、「DHCPDISCOVER」、「DHCPOFFER」、「DHCPREQUEST」、「DHCPACK」と教科書通り流れてて思わずニヤッとする。
無線のチャンネル設定はさすがに自動設定に任せる。
もっと広い部屋などにアクセスポイントを複数台設置する場合はサイトサーベイを行い、各機の設置場所とチャンネル設定の最適な設定を決める。まぁそんな仕事ないけど。

エコ的な考えでは2.4GHz帯は止めたいとこだけどVaioも無線で繋げたいのでとりあえず5GHz、2.4GHzを同時利用する。
XBox360は今まで通り有線LANなので繋ぎかえるだけ。

で壊れた旧ルーターは破棄だけど、ふと見るとMACアドレスを示すシールが貼ってあった。WAN側、有線LAN側、無線LAN側と一台で3つも使っている。こういうのって解放しないで良いんだろうかと思ってしまう。(これもエコ的な考えだが、MACアドレスは理論上70兆個も割り振れるので解放の必要はないはず)

2015/05/10

関数型プログラミングに目覚めた?

「ずいぶんとダサいコードを書いているのね」という言葉で始まる某書籍を読んでみました。
『関数型プログラミングに目覚めた! IQ145の女子高生の先輩から受けた特訓5日間』のことです。先の書き方では検索に引っかからないので書名を載せときましょう。

以前からぼんやりと関数型プログラムが出来るようになりたいと思ってましたが、ネットでちょっと調べる程度で出来るものではなかったです(自分にとっては)。
でたまたま平積みされていた本書を立ち読みすると、ストーリー仕立てで面白そうだったのと、1300円と安価だったので即購入。GW一杯かけて読むことにしました。本書は丁度5月1日に発売されていたのでそういう読み方も想定していたと思う。ちょうど5日間だし。

内容としては「0から9までの数をすべて足すコード」を、関数型プログラムで書くまでが前半の100ページ以上かけて説明されています。関数を一個一個定義していって最後に関数型のコードで「0から9までの数をすべて足すコード」ができるところ、フィボナッチ数列を関数型プログラムで求めるところでかなり感動してしまった。

この前半はかなり充実した内容だと思う。関数型プログラムがどうしてもよく分からない、そもそもなんでオブジェクト指向ではダメなのか、何から始めればいいのかとか、最初の取っ掛かりが掴めずにいた自分にはピッタリ嵌ってしまった。また読み物として前から後ろに読んでいっても復習の章があったりして自然と考え方が定着します。普通技術書は重要なことが書いてあるページは読者が覚えておいて何度も開き直すような読み方になると思いますが、読み物として読んでいってる人にも理解させようという気概がある書き方みたい。
なんというか、ストーリー仕立てということもあるしとても情熱的な書き方になっている。一度オブジェクト脳になってしまった頭をパラダイムシフトさせるにはこのくらいの熱意が感じられないと難しいのかも。今まで関数型プログラムの壁に当たって引き返していたのが、女子高生にダサいコードと罵られたことで何としてでも超えてやろうと思えたわけだ。

前半に比べると後半は技術的な内容、というか関数型プログラムに関する説明が少なくなって、React.jsの解説になっていくのでちょっと話がずれてるかなーという感じ。ラムダ式だのカリー化だのを同じ調子で説明してくれれば良かったのにと思う。
読み終わってみると、そもそもラノベに近い読み物だったのかと思える。

とにかく関数型の最初の取っ掛かりとしてはかなり良いものが読めたという気がする。ただラノベ要素が余計というかちょっと煩く感じる部分はある。とてもある。

読み終わってアマゾンを見ると本書に関して内容が薄いとかそもそも誤解に基づいた主張とか、レビューの点数があまりに低いのでビビった。
 まぁ本の内容が正しい、ということより、内容がどうであれその本に影響を受けて関数型プログラムの習得に強い動機付けがなされた人、あるいは最初の壁を突破した人が一人いる、ということの方が重要なので、個人的には超おすすめ。

関数型プログラムをやりたいけどよく分からない、って状態で(女子高生に罵られるのがそんなに嫌いじゃない人が)読むと絶対面白いと思う。

というか普通に考えて発売から1週間足らずでこれだけのレビューを集めてる、そんでほとんどが低評価ってのがなんていうか、、本の内容がどうというより余程嫌われてるんですねこの作者w。

Amazonのレビュー見てると、どうもこの作者の人となりによって不当に評価されている気がする。この本のターゲット層は関数型プログラムなんか出来ないって人で取っ掛かりを求めてる人なんじゃないの?
言語として、関数型プログラムなんか出来ない人にも馴染みの深い、関数型プログラムが書けるものって、JavaScriptがぴったりだと思う。
で関数型をこれから始める取っ掛かりって意味で関数型の考え方とか作り方とかをここまでページ数使って簡単に解説してるものは他にないと思うけど。

変な先入観を持ってこの本読まずに、難しい本を最初に手に取って「やっぱ関数型って意味わかんね」ってなるくらいなら、この本を最初に読めばいいと思う。
まぁ、表紙が良いのと値段も安いので買う人多いと思うけど。

なんと著者のブログでこのレビューが紹介されているのだ
すさまじい長文なのだが真ん中辺り(と書いても無駄なくらい長文)にしっかりと引用されている。