Hatena::Grouperlang

檜山正幸のErlang未確認情報 RSSフィード

 | 

2010-01-13 (水)

続・久しぶりに使うと -- 後で読めるようにする

| 10:05

リハビリ・サンプルとして、自分で書いたErlangコードを眺めてみたが、意味不明なところがある。それで思ったことを書きます。

僕の習慣:変数名がだいたい大文字1文字。表向き/建前の理由としては; Erlang変数局所変数しかないし単一代入だから、スコープは狭く、値のバインディングを追跡しやすい。だから、短い名前でも大丈夫。

でも、やっぱり1文字はマズイな。純粋な数値計算やリスト処理だと、N(数値のつもり)とかL(リストのつもり)とかで十分なんだけど、背後になんらかのセマンティクスがあるときは、それを示唆する名前を付けないと意味不明。例えば、LじゃなくてPersonListとかね。変数名が長くなる時はアンダスコア区切りよりキャメルケース(ただし、もちろん先頭大文字)のほうがいいような気がする。(先頭大文字はキャメルに見えないから、キャメルケースって言わないのか?)

それと、アルゴリズム書くより(それが可能なら)列挙した方がいい、と思った。例えば、mod 3 の足し算は普通次のように書くわな。

sum_mod3(N, M) ->
    (N + M) rem 3.

関数の定義域を {0, 1, 2} に確実に制限したいなら:

sum_mod3(N, M) when 0=<N, N=<2, 0=<M, M=<2 ->
    (N + M) rem 3.

だけど、次のように書いた方が分かりやすいんじゃねっ。

sum_mod3(0, 0) -> 0;
sum_mod3(0, 1) -> 1;
sum_mod3(0, 2) -> 2;
sum_mod3(1, 0) -> 1;
sum_mod3(1, 1) -> 2;
sum_mod3(1, 2) -> 0;
sum_mod3(2, 0) -> 2;
sum_mod3(2, 1) -> 0;
sum_mod3(2, 2) -> 1.

別な例を挙げると:

max(N, M) when is_integer(N), is_integer(M) ->
    if
	N >= M -> N;
	true -> M
    end.

上のより、次のほうが分かりやすいと感じる。

max(N, M) when is_integer(N), is_integer(M), N >= M -> N;
max(N, M) when is_integer(N), is_integer(M), N <  M -> M.

冗長ではあるけれど、それぞれのケースをズバリそのまま記述しているから具体性が高い。

短い名前も複雑なアルゴリズムも、読む側に推測だの解釈だのという知的努力を要求する。知的努力を要求しない書き方は、冗長、ダサイ、カッコ悪いになるんだけど、トータルなコストを勘案すると、なるべくアホっぽく書いた方がかえって良いみたい、と思った。

VoluntasVoluntas2010/01/13 11:57Erlang 自体のソースコードも列挙系が多いですよね。読みやすさと言うよりは速度の面もあるのかもしれません。
if の使いどころが未だによくわかってないです :-P

m-hiyamam-hiyama2010/01/13 12:07Voluntasさん、
> 読みやすさと言うよりは速度の面もあるのかもしれません。
定数列挙ならジャンプテーブルのような最適化が出来そうですね。パターンマッチの多方向分岐でも最適化手法があるんかしら?
> if の使いどころが未だによくわかってないです :-P
ifはなんだかワカランですね。whenガードと同じ感じの条件で多方向分岐ってことでしょうが、そんなん、あんまり出てこないし。

 |