Haskell の >>= とか >>，F# の |>， JavaScript や Ruby のメソッドチェイン， C# の Extension Methods を使ってみて思ったのが，チェイン時にレシーバの型と戻り値の型を変えられるのは実はとてもありがたいということです． 動的型付け言語である JavaScript や Ruby であれば，元から戻り値の型は実行時にころころ変えられるので，何を今更，な話でしょう． じゃあ静的型付け言語である Haskell ，F#， C# ではどうかというと，パイプライン後段のメソッドルックアップが，パイプライン前段のメソッドルックアップに依存しているというのがとても便利です．パイプライン前段のメソッドルックアップをちょっと変えてやると，そこよりあとの段については コンパイラ が最適なメソッドを選び直してくれるのです．LINQ to Object の ソースコード が，「より優先度の高いルックアップルールを using で導入するだけで」，LINQ to SQL になるってのはそういうことですよね．

上の「ここまで読んだ」のところの型が，Even なのか SpecializedEven なのか書かない方がむしろ良くね？ というわけです．特定の型を強制したければ，CastTo<T> という処理でも作って明示すればよいでしょう． 変数代入に紛れてこっそりアップキャストされると，メソッドルックアップルールを活用したメソッド選択/差し替えの結果が変わってしまいます．

ところ変わればプログラマの意図も変わる

以上のようなことを思ったのは実は昨年暮れだったりするのですが，あとはまあ『ベイダー日記 2008-02-21』を読んでまた漠然と思い出したり，最近流行のローカル変数のアップキャスト議論で思い出したり．

わかりきったとこならvarでもいぃんとちゃうの?

これについても同意っちゃー同意なんですけど、

僕がこだわるのがコンパイラの型推論が

プログラマの意図と一致しないことがあるなー、と。 var children = new List<Child>(); 僕はおそらく、このテの(省略目的の)varは使わない気がします。

childrenはList<T>でなくてはならないとは思っていない、

Childの集合でありさえすればえぇのや、 ICollection<Child> children = new List<Child>(); なのよね僕のキモチ的には。

この辺は仮名漢字変換を単文節でぶつ切り変換するのが好きか，長文で一気に変換するのが好きかみたいなもので，もはや好みの問題かなぁという気もします．私も昔はぶつ切り変換的にコーディングしていましたが，最近は逆です．型を介してシンプルなロジックを連結するスタイルに変わりました．シンプルなロジックの連結だけを書いておけば，最後にコンパイラが型を介して一気に巨大なロジックを組み立ててくれるよ教に宗旨替えです．

半端なローカル変数や private メソッドを排すことで，思考速度とロジックの結合速度が一致してくる感覚は楽しいですね．「この流れで行けばうまく組み立て挙げられる」と確信しているときに，いちいち型を書いたりしないですよと．型のミスマッチはコンパイル時に検証されるので，意図とコードがズレていないかのみが重要です．その意味では，ぶつ切り変換的なコーディングも，込めている意図があってそれとはズレていないよというだけの話なんでしょうけどね．スタイルの違いなので，まあ好きな方を使えばよいのでしょう．

私はというと，長文変換的なコーディングをするようになって，関数テンプレートの型推論*1やラムダ式の型推論，メソッドオーバーロードのルックアップがいかに重要かというのが納得できました．これに関しては，実際に自分でやってみるまで，いくら文章で説明されても実感が伴った理解になっていなかったと断言できます．

今の自分が過去の自分に「var や let で定義した変数は，型変換という副作用を持たないが故に，処理と処理の連結器のように使うことができるのです」なんて言ったとしても，今の自分が意図しているところはなかなか伝わらないんですよね，多分．とまあ多分にキモチ的な問題なんだと思います．