S式が必要な理由 / Schemeでは足りない部分
今日は考えながら書くので、結論は一番最後。
関数指向言語は色々あるものの、自分はどうしてもS式ベースの書式を持った言語を選ばざるを得ないようだ。
その理由を色々と考えてみた。
その結果は、自分が、究極的には「コードを生成するコードを書いて、あとはそいつに任せる」ようにしたい、と思っているところにある、という結論になった。
「人間が読み書きしやすい」よりも「コード(プログラム)が読み書きしやすい」方を半ば優先している、という事のようだ。
(個人的には、S式は人間にとっても(エディタの助けは必要だが)充分に読み書きしやすいと感じている(そうは思わない人も少なからず存在するようだが)。複雑な文法を憶える必要がほぼ無いのも良い。構文なんてコンピュータ側から見れば無意味なんだよ!なんでそんなのをわざわざ憶えないといけないんだ。)
そして、S式ベースの言語の中では、(eval expr (null-environment 5))のできるSchemeが、一番、コードジェネレータを書くのに相応しいように思える。多分。
(この部分は少し調査が足りてないので、他にもこれ相当を持つ言語はあるかも。)
とは言え、それなりの期間Gaucheを使って、何かを書いたり、書きかけて放置したりしてきたものの、どうにもSchemeでは不便だと思うところも何箇所か出てきた。
- Schemeではリスト(というかツリー)を扱う事が多いものの、自分のやってみた範囲ではどうも、ツリーは他の何らかの実体(例えば、ネットの向こうの何か、とか)のマップである事が多く、そういう時はデフォルトで遅延評価が欲しくなる。最初に全部読みたくないが、いちいちdelay/force(的な何か)をかますのもちょっと面倒。
- しかし、デフォルトでの遅延評価を考えると、Haskellのように参照透過性が必要になるが、個人的には「奥の手 / 最終手段」としての副作用操作も残しておきたい。あとcall/ccも捨てられない。
- その延長で、手続きに無限リスト/不完全リストの引数を渡したい時もあった。勿論、Schemeではそんな事はできないので、第一引数として(無限/不完全かも知れない)リストを受け取る手続き、として書いた。でもそれなら、receiveもvaluesも廃止して、lambdaの引数は常に一つ、lambdaの返り値も常に一つ、代わりに引数/返り値がlistの時はパターンマッチで親切に切り分ける機能が別にあればいいんじゃないの!?……と思った(が、これがベストかどうかまではちゃんと考えてない。思い付いただけ)。
- 一部のマクロの括弧の数が憶えにくいのも思い出した。letとか。
- 個人的には、letについては、未来での並列実行性なんか気にせずに廃止して、let1を基本コンポーネントにした方がよかった気はする(勿論、勝手にそう思っているだけで、本当にそうなのかどうかの検証なんてしてない)。
- 一部のマクロの括弧の数が憶えにくいのも思い出した。letとか。
と、色々と文句はあるものの、何かを実装する際に大きな障害になる程の問題は別にない。
別にない、が……微妙に不満はある。
しかし、だからと言って、他にもっと適切そうな言語も無いし(とは言え、Liskellは気になる)、ポールグレアムのようにArcを作ってメンテする精力もない。
だから、ある程度の不満はあるものの、Schemeが一番マシだという事で、使い続ける事になるだろうなあという予想になっている。
完全に理想の彼女(または彼氏)が現実世界に居ないのと同様に、完全に理想の言語も現実世界には無いので。
(勿論、少しでも理想に近くなるように「育てる」(または「歪める」)事は可能だろうけど。)
結論。