自作関数型言語その後
その後、自作言語TFLのほうも、バグを潰したり標準ライブラリを整えたり、こちらにチュートリアルを纏めたりなどとしていました。
基本的に短期間で実装した言語なので、どこかでボロが出るだろうなとは思っていたのですが、とうとう今日、恐れていたことが起こってしまいましたw
http://d.hatena.ne.jp/camlspotter/20100714/1279072171
こちらで解説している「高階関数パズル」というのが、面白かったので、自作言語で実際に書いてみたのですが、どうやらこの言語ではどう書いても処理できない事が解ってしまったのです・・・
以下が苦心の後。
$ ./tfl.jar -i initial Load sclipt complete - initial > twice = f -> x -> `f `f x > twice {x -> +[x,1]} 0 [2.0] > (twice {twice}) {x -> +[1,x]} 0 [[\x], 0.0]
twiceを二つ連ねた結果が [[\x],0.0] となっていますが、評価の順序に問題があって、(((\x,nil),(0.0,nil)),nil) というS式になってなってしまい、それをリストとして出力したため、こんな表示になっています。(\xというのはラムダ式の引数を表します)
もうちょっと中身の話をすると、「右結合なので明示的に遅延評価するために小手先の対応をしている。」という事と、「関数の戻り値が問答無用でリストになる」という事が原因です。
色々と図を描いたりして考えてみたのですが、どう足掻いても無理みたいです。
幸いこんなテクニカルに高階関数を使うようなシチュエーションはそうそう無いと思われるので、実質的な問題にはなりにくいと思われますが。(それよりは数百件のリストをまともに扱えない事のほうがよっぽど問題)
仕事、趣味問わず、開発における「小手先の対応が引き起こす弊害」の良い一例になるのでは無いかと思います。
なんにせよ、この言語はもうちょっと色々やってみたい事があるので、当分はのんびり拡張し続ける予定ですが、これで一つ、限界が見えた感じです。
※おまけ、上のURLにもあるけど、Haskellで自分でやってみた
Prelude> let twice f x = f (f x) Prelude> twice (1+) 0 2 Prelude> twice twice (1+) 0 4 Prelude> twice twice twice (1+) 0 16 Prelude> twice twice twice twice (1+) 0 65536
ううん、不思議。