メッセージ。 - Haskellでよくやるミス

# Haskellでよくやるミス

つまらないミスで躓き、何時間もロスして嫌になった。よくやるミス(バグの元)なのでメモしておく。

  map (\l-> let (u:l:ss) = stringSplit "\t" l in (u,map read ss))
      $ lines cs
Haskellでよくやるミス

このコードを動かすと、(たぶん遅延評価とのコンボによって)プログラムが固まってしまい実行が前に進まなくなった。なぜかというと、要するに変数名がバッティングしているのだ。mapの中で「\l->」として変数lを使用しようとしているのだが、一方で「let (u:l:ss) = 」としてLet式の中でも値を変数lに束縛しようとしている。

このようなコードは、Schemeでは問題なく動く。より内側にある変数束縛(この場合はLet式)が、外側の変数束縛(\l->)より優先(隠蔽)するので、「\l->」をまったく気にしなくてよくなるのだ。変数名を考えるのが面倒なので、ぼくはこういうことをよくやる。ところがHaskellでは、このようなケースで変数lがバッティングしてしまうのだ。その結果、プログラムがまったく想定していない挙動をすることになる。

とくにHaskellでは、型宣言を併用することで極端に短い変数名を使うことが多い。変数名が短くても、それがなにを意味するのか、型を見ることで判別できるからだ。しかし、変数名が短くなったことによって、変数名がバッティングしやすくもなった。そして変数名がバッティングしたときのペナルティは非常に大きい。またGHCコンパイラも警告してくれない。

なので、この件についてはよくよく注意してプログラムを組まなくてはならない。>自分
2009-07-13 23:46:37 / ふじさわ / Comment: 0 / Trackback: 0

Comment

コメント投稿機能は無効化されています。

Trackback

TrackBack投稿機能は無効化されています。