パッと見の印象ほど複雑ではないし、難しくもない(入門書の例なんだから当然か)。いくつか明文化されていない設計方針を読み取れれば、かなり見通しがよくなる。
状態遷移モデル
オートマトンがどうとか理論的なことはよく分からないが、「状態」と「状態遷移」の考え方が使われていることは素朴に理解できる。状態は、全体が receive … end で構成された関数として表現されており、メッセージの受信を引き金として別の関数を呼び出す(=遷移)か、末尾再帰で自分自身を呼び出す(=遷移無し)、もしくは終了する。
状態を表す関数は名前も特徴的である。普通の関数は「動詞+目的語」が多いが、状態の関数は「形容詞または*loop」の形をしている。
この状態遷移モデルについて、本文中では11.3のチャットクライアントの説明の中でわずかに示唆されている。どうせなら状態遷移図でも載せておけばより分かりやすかったのではないかと思うのだが、説明が煩雑になることを避けたのか、あるいは後々OTPを用いる際には不要になる概念なのか……今の段階ではまだ分からない。
オブジェクト指向
状態遷移モデルにおける「状態」の関数は、オブジェクト指向における「オブジェクト」との類似性も併せ持っている。すなわちプロセスがインスタンスであり、ループの引数がインスタンス変数であり、応答するメッセージがメソッドである。io_widgetが特に分かりやすい。
この類似性は、ある意味当たり前ではある。なぜならメッセージ送信モデルはオブジェクト指向の先祖の一つだからだ。
……
状態遷移モデルにせよオブジェクト指向にせよ、様々なプログラミングパラダイムを全てプロセスとメッセージ送信に還元していくのがErlang流、という理解で良いのだろうか。
最後にコードの中に見つけた変なところを挙げておく。
- io_widget:update_state/3 は不要。またio_widget:loopで{updateState}を受ける部分も不要
- chat_group:delete/3 で、lists:reverse/2 の引数が逆(これだと削除するごとにリストが逆順になるので意味がない)
- io_widget:widget/1 内のpackerの設定が変。maxよりminが大きかったり、minとmaxが同じだったり(fixedを使えば済む用途のはず)