おがさわらなるひこのオープンソースとかプログラミングとか印刷技術とか

おがさわらなるひこ @naru0ga が技術系で興味を持ったりなんだりしたことをたまーに書くブログです。最近はてなダイアリー放置しすぎて記事書くたびにはてな記法忘れるのではてなブログに移行しました。

クリエイティブ・コモンズ・ライセンス
特に断りがない場合は、本ブログの筆者によるコンテンツは クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンスの下に提供されています。

Erlang Super Lite [Chapter 2]

Erlangといえば「Prolog大好き!」「でも後に続く言語ないんだよねー」とあちこちで言いまくっていたら「Erlang ちょっと Prolog っぽいらしいよ」と言われ、飛行機本を買って読んでいたら文法は確かに近いしパターンマッチはユニフィケーション、でもバックトラックがないなんて……と落ち込んでいたら、あれの並列処理って要はヒューイットの Actor じゃねーか? ということに思い至り、あー勉強しなきゃなーと思ってたらこんな素敵なイベント発見。そりゃ行くさ。

なんかついつい語りたくなっちゃってダラダラ下らないことを喋ってしまいました。すみません。>ALL
喋った&記憶に残ったことをメモっておきます。

Chapter 2 までの復習

  • [X|Y] を cons 演算子というのは、PrologErlang もパターンマッチングによる逆演算があるので car / cdr / cons が一緒に表現できるため。
  • 関係演算子が =< >= なのは Prolog の影響のはず。「矢印にならないように」と覚えてください。
  • 変数が大文字始まりも Prolog からだと思う。小文字symbol の場合は "_" をつける。Erlang の場合は _hoge は内部変数っつか「いちおー名前はつけたけど参照しないでね」って意味なのでちょっと違う。
  • 再帰のときに一時変数を使いたくて作る arity は Prolog だと名前を変えるべきという慣習があるので Erlang もそれを踏襲しているのかもしれませんね。SICP でも xxx_iter って奴がしょっちゅう出てくるけどあれみたいなものか。

Chapter 3

case とか if について
  • case はパターンを書き、if は Guard を書くのが違い。
  • 飛行機本でピンとこなかった Guard の意味がやっと分かった気がする。
    • つまり Prolog だと一階述語論理だから左に述語一個しか書けないけど、「ただしこういう場合ね」って補足条件を書けるってことか。
    • 例えば Prolog だと、評価順は上からなのでこうとしか書けない。
factorial(0) :- 1.
factorial(N) :- N * factorial(N - 1).
    • Erlang だと Guard を使うことによってこう書ける。
factorial(N) when N > 0 -> N * factorial(N -1).
factorial(0) -> 1.
    • んでなんで Guard にユーザ定義関数を使えないかというと Guard はあくまでも条件式なので「いつも同じ」が成り立たないといけない。
      • Erlang は reassignment ができない (= 言語レベルでは副作用がない) から大丈夫に思えるけど、io 呼んだ瞬間に副作用が起きてしまう。それを禁止したい。だからまるごとユーザ定義関数禁止にしたと。
  • パターンマッチと case/if のどちらを使うべきかかという点についてはテキストでは「どちらの書き方も等価である」としか書いてない。もしかしたら並列処理だと何か違うかも *1
再帰
  • 末尾再帰の場合ループに最適化されるからメモリ消費量も少なくて早いってのが定説だけど Erlang はかなり改善されてるから頑張って末尾再帰にする必要はあんまりない。
    • でも並列処理の場合無限に回る再帰とかあるけどそれは末尾再帰じゃないとスタック食いつぶしちゃうよ。
ちょっと脱線:tuple について
  • list 一個でよさそうなのになんで tuple みたいなもんがあるの?*2
    • tuple は要素をパターンマッチできる。この理由が多分一番大きい。
    • Key-Value で値が持てる。
    • たぶん内部構造も違うんじゃないかな。List はデータ構造的にかなり重いので。
    • 脱線だけど Ruby は Big Class といって一個のクラスに機能をたくさん詰め込む傾向がある。だからコンテナが多い言語は僕的には「なんでそんなコンテナがいるの?」と常に疑問に思うのだ。
例外
  • 例外処理は普通だけど throw でどんなものでも投げられること、catch はパターンマッチで捕まえるところがミソではある (笑)
Debugging
  • Debugger は EclipseErlang IDE を使うのがおすすめ。
    • ただし Erlang 起動時にコンソールが起きるんだけど、終了してもコンソールだけは生き残るのはご愛嬌。*3
    • まだアルファ版とのことだがステップ実行やブレークポイントの設定、変数の値の参照、など一通り揃っているのでおすすめ。

第9章

なんでいきなり飛ぶのかというとまずは sequential programming を一気に片付けようというお話。

高階関数関数型言語とはなんぞや、など
  • fun()*4 の end ってちょっとキモいよね、という話。
Z = fun(X) -> 2 + X end.
    • 一文中にいきなり「end」って出てくるのがキモい。明確にブロックとか分かる文法表現使ってほしい。
    • でも one-liner 的にはそういう書き方がうれしかったり。
    • end といえばなんで ruby は begin-end なの?
      • Eiffel の影響って matz さんが書いてた。
    • そういや「Cプログラミング診断室」で #define begin { みたいなのあったよね。
      • あれは Pascal の影響でしょう。
      • まあ厳密に言えば Algol 60 の影響なんですが。
      • Algol の頃はすべての計算機で "{" とか使えるとは限らなかったのさ。
  • なんか Erlang って書いてると関数型言語って気がしないんだけど。
    • 関数型言語ってそもそもなに?
    • 無名関数があるから関数型? じゃあ ruby は proc とかあるから関数型?
    • map があれば関数型? でもあんなのどの言語でもすぐ書けるよね? 組込みかどうかは意味論的には意味ないし。
    • 本質は「関数の戻り値を引数に渡して、その戻り値をまた引数に渡して」といって計算が完結する計算モデルなんじゃないの?
      • この場合の「関数」は数学的関数なので、同じものを入れたら同じ結果が出てこないといけない。
      • だから再代入があったら pure じゃない。というのがオイラ (naruoga) の理解。
      • つことで Erlang は「一個の関数の表現として複数の arity がある値を返さない arity がある*5」という意味では関数型っぽくはないけど、破壊代入を許さない、結果を次々と渡していくという計算モデルだとすれば関数型。
      • そもそも「関数型プログラミング」という概念は 1977 年、Backus の FP で提唱されたものなので、「Lisp関数型言語」は後付けに過ぎず、Lisp が持っている機能があるかどうかで関数型言語かどうかを考えるのはナンセンス。
包含リスト
[X || X <- Rest, X < Rest]
  • この構文は許せるか? Xが先に来るのってキモくない?
    • 数学だと「すべての x において、...が成り立つ要素の集合」とか普通なので違和感がない
    • でも matz さんはあんまりこの構文が好きじゃないらしい
    • ので ruby には入らないとか。
Binaries
  • まー言っていれば「バイナリを作るための構造体 with 便利な関数」
  • ミソはここも包含バイナリが書けて、なおかつパターンマッチができること。
  • 通信のためのヘッダつくったりに便利。
Erlang のライブラリの話
  • ちょっと凝ったことをしようとするとライブラリがない
  • JSON 操作したりとか
  • 使えそうな奴は日本語通らなかったりとか
  • 多分難しい話じゃないので馬力でなんとかなりそうだけど、みんながそうやるのイケてないよね。

そして演習

  • ぜんぜん演習やらなかったので各自自習しましょう (^^;)
  • 演習 3-10 は文書の折り返しの話。filled と言えばある幅に合わせて折り返す。後ろは揃わない。justify と言えば両端揃え。英文では基本ですよ (^^)。

*1:むろん Prologer としては if とか case とか使ったら負けである。

*2:関係ないけど Python の tuple は immutable で List は mutable という明確な違いがあるそうです。

*3:これは後ほど Masahito さんに Twitter でフォローいただきました。感謝!

*4:Erlang の無名関数の書式。

*5:Prolog 脳なので間違えた。Erlang は最後に評価した結果を常に返すので、値を返さない式は存在しない。ただ Prolog 風に arity を複数書いてパターンマッチでどっちかを使うというコードを書いていくこともできるということを意味してます。

*6:矢印の向きが思いっきり反対になってたので修正。おはずかしや。