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を基本コンポーネントにした方がよかった気はする(勿論、勝手にそう思っているだけで、本当にそうなのかどうかの検証なんてしてない)。


と、色々と文句はあるものの、何かを実装する際に大きな障害になる程の問題は別にない。
別にない、が……微妙に不満はある。
しかし、だからと言って、他にもっと適切そうな言語も無いし(とは言え、Liskellは気になる)、ポールグレアムのようにArcを作ってメンテする精力もない。
だから、ある程度の不満はあるものの、Schemeが一番マシだという事で、使い続ける事になるだろうなあという予想になっている。
完全に理想の彼女(または彼氏)が現実世界に居ないのと同様に、完全に理想の言語も現実世界には無いので。
(勿論、少しでも理想に近くなるように「育てる」(または「歪める」)事は可能だろうけど。)


結論。

  • まだ、他にもっと良い言語の探索は行うものの、おそらく、自分が作りたいもの(コードジェネレータ)を書く為に、Scheme以上に適した言語は見付かりそうにない。
    • S式(またはそれに類する、コードとデータが同じ扱いである書式)を持つ事。
      • S式以外を選ぶ場合は、更に、readとevalが分かれている事も重要?
    • 可能な限り、空に近い初期状態の評価環境が得られる事。
      • 勿論、望むならその中に好きな物だけを持ち込める事。
  • 以上の結論が出たので、どんどんSchemeでコードを書いていこう。
  • 気力が減少してきたら、山本弘やイーガンを読み直そう。