perl is 神

このお話について
http://www.kmonos.net/wlog/88.html#_2233080818


http://d.hatena.ne.jp/gnarl/20080820に一票。


以下全部勝手な妄想で
上のお二人のおっしゃっていることもわかってないかもしれません、
と前置き↓


ちょうどコンパイラ作ってて
k.inabaさんのアイディアがおもしろそうなので
ちょびっと脳内で検討してみたのですが、
彼のアイディアはつきつめると
「例外を2系統用意する」のと同じことだと思ったのです。
例外を発しない疑似返り値であるところのリッチNULLを
うっかり値として評価したら例外が発生するに決まっているからです。
と考えたときに、2系統なのはなぜなのかと。
1系統かn系統でないとキチャナイのではないかと。
これを単純化してn系統だと考えるとつまり、
リッチNULL=皮付き例外であって
リッチNULLを値として評価した結果、別のリッチNULLになる可能性も
あるということかなと。
で、まあ、あっても困りはしなさそうな気がするけど
自分には必要ないモノと思ったので興味は失ったと。
(掲示板にはこの辺のことをすべてすっとばして書き込んでしまった)


一方それとは別の話として、例外かどうかを決めるのはクライアント側だ
というのは前から常々思っていて、
セマンティクス的なことは切り離して
例外システムは制御構造と割り切って使うべきなはずだ、と。
(この結論はgnarlさんとは正反対か)
滅多にないとかよくあるとか、致命的とかそうでないとか、
そういうことを呼び出される側が恣意的に決めると
呼び出す側は一貫性が得られなくてかえって困る。
そんなのは状況によって変わるから。
たとえばゲームだと大概のことは致命的側に傾く。
しかしその立場で考えると、JavaだのC++だののtry...catchは
思想的なにおいが強すぎると。
字面的に鈍重すぎるから囚われる。
RAIIの方が便利なのはどういうわけなのかと。


でまたそれとは別でperlの||演算子が結構好きで、
話が早くていいなあと。


これらが混ざりあったときに、「||->」を思いつきました。
まーなんか最近知らない言語もだいぶ増えてきたので
すでにありそうな気もしますが。
k.inabaさんの掲示板から抜粋すると、
「正常処理では値を持ったままショートカットし、
例外がでたら次の式に進む演算子"||->"」
です。


「確信してたら例外」に対しては、単に

        v = d.find( k );

と書くことができ、「確信してなければnull」(とかデフォルト値とか)に対しては

        v = d.find( k ) ||-> "default";

とか書けるので、実際にnullが帰ってくるワケじゃないですけど
nullでもdefaultでも好きな値が帰ってきたように見せかけることが
小さい手間でできる。
連鎖は

        v = d0.find(k) ||-> d1.find(k) ||-> d2.find(k) ||->"default";

特定の例外にのみ反応するなら

        v = d0.find(k) ||->(NotFound) "default";

とか? まあ気色わるいからあまり複雑なときは普通にcatchして
パターンマッチしろって感じで。
この演算子の弱点は、拾わなく良さそうな例外まで
全部拾っちゃうことですかね。最後の形式なら選択できそうだけど、
軽さに欠ける。
というわけで、多値とかoptionで似たようなことができるのなら、
そっちが本命ってことで、
例外は今の鈍重な形式のままでもいいかな。
optionがbuilt-inの機能なら同じ演算子が使えるか。


連鎖が必要なければ、オーバーロードして

        d.find( s );                   // <= 例外
        d.find( s, when_not_found )    // <= 返値

で無問題な気がしなくもないですけどね。


意味としては、OCamlの方法は十分に正しいと思っています。
書くのがすげえめんどくさいだけで。


と思ったんですが、どうでしょう。