鍋あり谷あり

テーマを決めずに適当に書いています。

型検査

まずは MTASC/AS2 の型検査の話の追補。
昨日は AS2 の型検査が役に立たないという話をたくさん書いたが、おととい書いているとおり、ケアレスミスを減らすのには役に立っていそうだと思っているし、その恩恵にはあずかっている。
id:soutaro さんが

var b:Number=true;

なんて間違いを犯す人間が本当にいるのかどうか

と書いている。
AS2のへぼい型検査の肩を持つと、

var b:Number = 1;
if ( 条件 ){
  var b:Boolean = foo();
  //十行ぐらい
}
b = false;

なら書きかねないと思う。思うのだが、ねらいはそこにあるのではなく、メソッドの返り値やプロパティを正しく変数に入れることにあるのだと思う。

var n:Number = "foo".charAt(0);

が正しいかどうかは、憶えてないとわからない*1

それと。

関数の引数にも型指定を付けられれば、annotationとしての意味はあるだろうけど、それも(MTASCでは)無理だったし…

とあるが、

function f( a:Number ):Number{ return a; }
function foo()
{
  var a0:Number = f( [] ); // type error Array should be Number
}

という具合に、引数にも型指定をつけることはできる。
しかし、これには抜け道があって:

function f( a:Number ):Number{ return a; }
function foo()
{
  var a1:Number = f( 0, [], f, _root ); // 引数の数が多くても気づかない
  var a2:Number = f(); // 引数の数が少なくても気づかない! a2 は undefined になる。
}

といった具合になる。
この仕様で行こうと決めた人の気持ちはわからなくはないが、やっぱりあんまりだと思う。
省略できない引数であることを示す文法を導入すべきだと思う。

で。
話は変わって、ruby なんかも含めた一般論。
理論家ではなく職業プログラマである身としては。
ML のような完璧な型検査をしてくれたらそりゃありがたいが、たとえば:

  • この変数には必ず Number しか入らない、という具合にソースに書くことができる。その変数に Number ではない値を入れたら例外発生。
  • 型指定付き変数の型がその型であることを利用して型推論をする。上記の例外が発生することが確実であるようなソースを発見したらコンパイル時エラー。

というような、プログラマの自助努力に頼った実装で、十分実用的だと思う。
私の場合、なんかの具合で変数の値が nil になり、その後 nil に 1 を加えようとした瞬間に例外発生というケースが多い。変数の値が nil になった時点で例外が発生したらちょっと楽になる。
型指定付きではない変数は今までの ruby/javascript/actionscript と同様に動くので、使えなくなったなどという批判は当たらない。
型推論から逃げているんだろ! とか言われたら反論しにくし、実行速度が型検査の分落ちるという批判もあり得る。なんか一貫性の欠けるしょぼい実装だなと言われたらその通りだし、美しくないと言われたら返す言葉もない。
とはいえ、型検査とは無縁の言語に無理矢理入れる型検査の落としどころとしては悪くないと思う。(突然文体が変わって)どうですか?

*1:charAt は String を返すので、エラー。文字コードが必要な場合は charCodeAt を使う