Forthコード

いかにもfothらしい”コード面に対する嫌悪感を説明してみたい。ただし、“いかにもforthらしい”には引用符をつけておきたい。確かにそれを許しているのはforth自体の特性であるとしても、自由度が高いことは何もかもが正当化されているということではないからだ。プログラマーに責任がかかってくるのである。

“いかにもforthらしい”コードの第一の問題は、何をしようとしているのか解りにくいことだ。ただし、それはスタック状態の変化が追えないからではない。非アルファベット記号が多用されているからでも、人為的な改行記号(C系の ; のような)がないからでもない。そういった初歩的なところで引っ掛かるのは読む側に問題があることも多い(例えば、スタックをどう手なずけるかとか、アレイをどう操作するかという話に集中する自称Forth愛好家は偽物(万年初心者)であり、相手にする必要はないと思われる。)。しかしそれら些末なこととは異なる理由で、なお何をしようとしているのか解りにくいコードがある。Forthコードでも解り易いものは極めてわかり易いのであるから、解りにくいコードを書く側に何か原因があるはずである。

Forthデザイン

現時点では、その原因はプログラムデザイン面でのある種の混同にあるのではないかと思っている。もっとも大きなところは、言語実装の側面と言語利用の側面との混同である。

Forthでは、実際、言語実装面と言語利用面との間に明確な境界が無く、それこそがforth言語の特性であると見ることができる。しかし、連続的であるということは、ごちゃ混ぜに混同して良いということは意味しない。forthの基本諸ワードを均質で一様な要素の集合として取り扱うことは論理的な紛糾を招くだろう。言語実装局面とアプリケーション局面のコンテクストの違いがコードの書き方に加える圧力を考える必要がある。forthはlow levelかつhigh levelな言語である、といわれる。これは正しい。問題はそれがごく標語的に流れてしまうように思われる点である。抽象度のレイヤーなら、どのような言語でも考えられる。しかし、その場合、低レベルであれ高レベルであれ、一つの階層の中では他の階層からシンボリックにひいてくる機能性を別とすれば、どの階層でも同じような均質なアプリケーションプログラミングを行うのが普通である。Forthの場合、単純に縦方向に積み上げていくのではない。そうすることもできるが、それとは異なるやり方ができるのがforthなのである。言語実装のレイヤを横に方向に広げることで、その上の階層における問題の解き方、あるいは問題の設定を変えるという方法があるのである。

しかし、私見だが、言語実装をサポートするワードは、アプリケーションレイヤーでのワードのように自由な使用法はできない。それは機械やコンパイラとアプリケーションプログラムをつなぐ領域であり、一定の堅固さが必要となるからである。また、そこでは、それによって拡大される言語領域によって何がもたらされるかという思考が必要となる。そこでは、確かに、抽象的な言語機能が考察されるわけではなく、プログラムが解く問題を指向して言語拡張が構想されるのではあるが、それは問題を解くアルゴリズムを考えることとは異なるものである。

デザイン思考の硬直化

しかし、アプリケーション問題が一定の型によってのみ捉えられるようになると、こういった言語実装部分の操作可能性は一般に無視され、全体を総動員して(つまり均質一様な集合として扱って)問題を解くことに集中するという思考が一般化してくる。すると、極めてアクロバティックな解法が「elegant」とか「cool」といった評価を受けることにもなる。規制によって成立している標準的なプログラミング言語では、それももっともな話ではある。しかし、forthはそのようなことをする必要がほとんどない言語であるように思われる。言語実装自体さえ拡張できる言語だからである。

まず、言語実装局面と使用局面とを混同したコーダーは、それらの局面がゴチャゴチャに混じりあったアクロバティックなコードを書く。これが、解りにくいコードの第一類型である。結果として、そのようなコードは環境依存的になりやすい。言語実装局面は、機械とそれに対応したコンパイラと言語使用局面とを縦断する領域だからである。言語実装を経て初めて機械の差異が吸収されるのであり、アクロバティックなコードはその点をないがしろにするからである。

通常のアプリケーションプログラミングとは異なる特殊な状況でのデザインのための思考がほとんど欠けている。少し慣れればforthでの言語拡張は容易である。そのために、いわば安易な言語実装拡張に走るのである。

最も残念な意見は、上のようなコードが“悪い”理由は環境依存的なことだ、という見方である。問題を完全に取り違えている上に、ポータビリティー神話への信仰が見え隠れする。その上、「標準に遵うシステムなら動作するはずである」という判断が、無闇なコードアクロバットに完全な免責を与えてしまう結果にもなる。
私見では、コンピュータの動作に対してプログラミングするのが真っ当なプログラマーであって、
コンパイラーやインタープリタなど特定の開発環境に対してプログラミングしようとするのはヘボプログラマーである。
言語拡張的にコンパイラーを変形するときでも、開発環境の不都合な動作をねじ伏せることに執心するのではなく、
変形を通してコンピュータの動作(低レベルで考える必要はなく、当の言語のマシン観にしたがえばよい)をプログラムすることにつなげること、
を第一に意識するのが筋であろう。

他方、難解なコードに直面して表面的な現象面だけを観察し、“悪者”を具体的に特定して、その使用を一般的に禁止したり、その使用を侮蔑するという態度を取るのがもっとも安易な“標準化”方法である。残念ながらコンピュータプログラミング世界ではこの安易な方法が最も標準的なのだ。権威筋による禁止と抑圧は、forthについてみれば言語実装局面にかかわるワード群に向けられがちである。しかし、十分な背景への考察なく現象面の表面的な概観に基づく限り、そういった抑圧はforth言語使用に歪んだ圧力をかけることにしかならない。とりわけ、言語実装の拡張が可能であることこそがforthの強みであるからには、言語実装を可能とする諸ワードを全て禁止するというわけにはいかない。特定のものを優遇し、他のものを抑圧することになる。すると、そこで優遇されたワードに過重な負担をかけるコードが推奨されることになる。結局、利用が奨励されるワードをアクロバティックに利用して、利用禁止されたワードの穴を補おうとするわけである。これが解りにくいコードの第二類型である。

言語実装局面と言語使用局面とが平板に言語利用局面として無差別に捉えられている限り、問題が解決されることは期待できない。禁止すべき例は増えていく一方となるだろう。

そういった、無理を強いているように(私には)見える、意図が解りにくいコードは、実際には、そこまでしなくとも可能なことを不自然なやり方で実現しているのではないだろうか。特定の問題とその解法から離れた「一般理論」ないし「教説」から引き出された一般的な禁則や推奨によって、初めから問題を見る目を歪めてしまっているところに、その解りにくさは発しているように思われてならない。禁則を守りつつ禁止された手段無しで同等の結果を得るという、人為的に作り出された難関をクリアーしてみせる、こけおどしの「cool」なのではなかろうか、と思うのである。

最終更新:2013年09月18日 11:36