「同一のもの」をつかんだ気になれる記述ができるかどうか?

http://www.rubyist.net/~matz/20070412.html#p01
http://alohakun.blog7.fc2.com/blog-entry-731.html
http://www.lingr.com/room/gauche/archives/2007/04/21
http://www.lingr.com/room/gauche/archives/2007/04/22

このへんの界隈の、プログラム実行中に変化していく状態の、オブジェクト指向言語と純粋関数型での書き方の違いの話。

いろいろコメントつけたり返事をもらったりしてたわけだけど、それでもやっぱり僕は「書きやすさ」が最重要な点だと思っている。どういう書きかた、考え方を好むかは「それまで自分が触れていじってきた言語や環境への慣れの影響が大きい」という話もわかるんだけど、それだけでは片付かないものがあるのかないのか、あるならそれが何なのかを見極めたい。

rubyhaskellを双方手足のように扱える人にとって、ある問題を解くときにrubyで書くかhaskellで書くかを選ぶ基準を考えてみると思考実験になるだろうか?実行速度が〜、実行する環境が〜、ライブラリが〜、文字コードが〜、とかとかとか現実にはそういう言語モデル以外の影響も大きいわけだけど、ここでは無視。まぁ、たまたま解こうとする問題には言語モデル以外の要因の影響はあんまり関係なかったとしよう。
双方を使えるんだから、その人は双方の脳内モデルのスイッチはできる。ではその人はその問題をどちらで解こうとするのか?

個人的にはある問題、作ろうとしているプログラムを考えた時に、「あ、これはRubyのほうが書きやすそうだ」とか「あ、これはhaskellだと楽だな」とか思うことはある。
ぱっと思うのは、lingrのログにもあるけど、haskellな世界では「同一」の概念がないこと。「同一」はなくて「同値」しかない。ある値を抱えているデータオブジェクトが複数あったとしても、抱えている値が同じならそれらのオブジェクトは区別できない。逆に、抱えている値がすこしでも変化してしまうと、それらを「同一」とみなすことはできない。一方、Rubyでは持っている値とは全く無関係に、「同一」という概念が存在する。値が関係ない「同一」が判定できるので、あるオブジェクトの値(インスタンス変数)を更新しても、「同一」のオブジェクトだと思っていられる。

例えば、シューティングゲームの中の自機や弾なんていうオブジェクトが座標という値をもっている場合、Rubyでは「自機オブジェクト」の座標値を変化させてオブジェクトの移動を表現するのに対し、haskellではある時点のオブジェクトから次の時点の座標を持ったオブジェクトを「生成」する。いわばオブジェクトの時系列順の列を生成して、その先頭を「今」だと思うことで、自機オブジェクトが移動したことを表現する。

もし、コーディングしてるプログラマが自機オブジェクトの「今」にしか興味がないんだったら、rubyだと直接ソース上で変数にバインドするなりしてひっつかんだオブジェクトが、時間が進んでもずっと「同一性」を保ってくれるので「楽」な気はする。
haskell式だとある時点のオブジェクトを変数にバインドしても、「次」の時間のオブジェクトは全く別のオブジェクトになるので、アクセスするのに1クッションいれないといけない。ま、haskellにはそういうのをラップしてくれるIORefってのもあるわけなんだけども、例によって例のごとく、モナドがもれなくついてくる。もうちょっと何とかならないものか、という気もするんだけど。OCamlつかっとけ、ってことかな。

結局、shelarcyさんがいうように、どっちがデフォルトのほうが嬉しいか、という話なのかな。デフォルトでないほうも楽に書けると嬉しいんだけど、そうするとOCaml使えって話になるんだろうか。OCamlでも何か書いてみるかなあ。
と、ぐだぐだになったところで今日はおわり。

ところで、yoriyukiさんのコメントの「純粋関数型言語では計算量的に書けないアルゴリズムがあったはずです。」は気になるなあ。どこでどう変わってくるんだろう。「値の更新」と「新たな値の生成」のコストが違うってことだよな。膨大な配列の一箇所だけを変更する、という操作がものすごく発生するようなアルゴリズムなんだろうか。