簡潔さは力なり
Original2002年5月
「代数記号によって小さな空間に圧縮された意味の量は、私たちがその助けを借りて行うことに慣れている推論を容易にするもう一つの状況です。」
- チャールズ・バベッジ、アイバーソンのチューリング賞講演で引用
Revenge of the Nerdsで提起された問題に関するLL1メーリングリストでの議論の中で、ポール・プレスコッドは心に留めておくべきことを書きました。
Pythonの目標は、簡潔さではなく、規則性と可読性です。
一見、これはプログラミング言語についてかなり非難すべき主張のように思えます。私の知る限り、簡潔さ=力です。 もしそうなら、代入すると、
Pythonの目標は、力ではなく、規則性と可読性です。
そして、これはあなたが作りたいと思うようなトレードオフ(もしそれがトレードオフなら)には見えません。 それは、Pythonの目標がプログラミング言語として効果的になることではないと言うことと大差ありません。
簡潔さ=力でしょうか?これは私にとって重要な質問であり、おそらく言語設計に関心のある人にとって最も重要な質問であり、直接対峙する必要がある質問です。答えが単純な「はい」であるとはまだ確信していませんが、良い仮説として始めるには良いようです。
仮説
私の仮説は、簡潔さは力である、または病的な例を除いて、それらを同一とみなすことができるほど近いということです。
簡潔さは、プログラミング言語がのためにあるもののように思えます。コンピュータは、機械語で直接何をすべきかを指示されても、同じように喜んで受け入れるでしょう。高水準言語を開発する苦労をする主な理由は、てこ入れを得ることだと思います。つまり、高水準言語の10行で、機械語の1000行が必要になることを言う(そして、より重要なことに、考える)ことができるようにするためです。言い換えれば、高水準言語の主な目的は、ソースコードを小さくすることです。
もし、ソースコードの縮小が、高水準言語の目的であり、何か物の力は、その目的を達成する程度であるなら、プログラミング言語の力の尺度は、プログラムをどれだけ小さくできるかということです。
逆に、プログラムを小さくしない言語は、ナイフがうまく切れない、または印刷が判読できないなど、プログラミング言語がすべきことをうまくやっていません。
指標
しかし、どのような意味で小さいのでしょうか?コードサイズの最も一般的な尺度は、コード行数です。しかし、この指標が最も一般的であるのは、測定が最も簡単だからだと思います。プログラムの長さの真のテストであると本当に信じている人はいないと思います。さまざまな言語には、1行にどれだけの量を置くべきかについて、さまざまな慣習があります。Cでは、多くの行に区切り文字しかありません。
もう1つの簡単なテストは、プログラム内の文字数ですが、これもあまり良くありません。一部の言語(Perlなど)は、他の言語よりも短い識別子を使用するだけです。
プログラムのサイズをより適切に測定する尺度は、要素数だと思います。要素とは、ソースコードを表すツリーを描いた場合に、別々のノードになるものすべてです。 変数や関数の名前は要素です。 整数や浮動小数点数は要素です。 リテラルテキストのセグメントは要素です。 パターンの要素、またはフォーマットディレクティブは要素です。 新しいブロックは要素です。 境界線上のケース(-5は2つの要素か1つの要素か?)がありますが、ほとんどのケースはすべての言語で同じなので、比較にはあまり影響しません。
この指標は、具体化が必要であり、特定の言語の場合には解釈が必要になる可能性がありますが、プログラムが持つ部分の数を測定しようとしていると思います。この演習で描くツリーは、プログラムを理解するために頭の中で作らなければならないものであり、そのため、そのサイズは、プログラムの書き込みまたは読み取りに費やす作業量に比例します。
設計
この種の指標により、さまざまな言語を比較することができますが、少なくとも私にとっては、それが主な価値ではありません。簡潔さテストの主な価値は、言語の設計におけるガイドとしてです。言語間の最も有用な比較は、同じ言語の2つの潜在的なバリアント間です。言語でプログラムを短くするために何ができるでしょうか?
プログラムの概念的負荷がその複雑さに比例し、特定のプログラマーが一定の概念的負荷に耐えることができる場合、これは、プログラマーが最大限に成果を上げられるようにするために何ができるかと同じことです。そして、それは私にとって、良い言語をどのように設計できるかと同じことです。
(ちなみに、古い格言「すべての言語は同等である」が、言語の設計ほど明白に間違っているものはありません。新しい言語を設計しているとき、あなたは常に2つの言語を比較しています。xをした場合の言語と、しなかった場合の言語を比較して、どちらが良いかを決めます。もしこれが本当に意味のない質問なら、コインを投げるのも同じです。)
簡潔さを目指すことは、新しいアイデアを見つけるための良い方法のようです。 さまざまなプログラムを短くできるものがあれば、それは偶然ではないでしょう。おそらく、役に立つ新しい抽象化を発見したのです。ソースコードから繰り返しパターンを検索するプログラムを書くことさえできるかもしれません。他の言語の中でも、簡潔さで評判の高い言語は、新しいアイデアを探すための言語です。Forth、Joy、Iconなどです。
比較
私の知る限り、これらの問題について最初に書いたのは、フレッド・ブルックスの人月の神話です。彼は、プログラマーは言語に関係なく、1日にほぼ同じ量のコードを生成するようだと書いています。20代前半に初めてこれを読んだとき、私はとても驚きました。それは、(a)ソフトウェアをより速く作成する唯一の方法は、より簡潔な言語を使用すること、そして(b)これを行うために苦労した人は、そうしなかった競合他社を出し抜くことができることを意味していました。
ブルックスの仮説は、もしそれが真実なら、ハッキングのまさに核心にあるように思えます。それ以来、私は、正式な研究から個々のプロジェクトに関する逸話まで、この問題に関する入手可能な証拠に注意深く目を向けてきました。彼を反証するものは何も見ていません。
私はまだ、私にとって決定的なものと思われる証拠を見ていませんし、期待もしていません。ルッツ・プレシェルトのプログラミング言語の比較などの研究は、私が期待していたような結果を生み出していますが、意味のあるテストを行うには短すぎる問題を使用する傾向があります。言語のより良いテストは、作成に1か月かかるプログラムで何が起こるかです。そして、私が信じているように、言語の主な目的は、(一度考えたことをコンピュータに伝えるだけでなく)考えるのに適していることであるなら、唯一の真のテストは、その言語でどのような新しいものを書けるかということです。そのため、事前に定義された仕様を満たす必要がある言語の比較は、少し間違ったものをテストしています。
言語の真のテストは、新しい問題を発見して解決できる程度であり、他の人がすでに定式化した問題を解決するために言語を使用できる程度ではありません。この2つは、まったく異なる基準です。 芸術では、刺繍やモザイクなどの媒体は、事前に何を作りたいかを知っていればうまく機能しますが、そうでなければまったく役に立ちません。たとえば、人物の画像のように複雑な画像を制作する際には、制作中に画像を発見する必要があります。そのためには、鉛筆やインクウォッシュ、油絵などのより流動的な媒体を使用する必要があります。実際、タペストリーやモザイクの制作方法としては、最初に絵画を作成し、それをコピーすることが一般的です。(「カートゥーン」という言葉は、もともとこの目的のために意図された絵画を指すために使用されていました)。
これは、プログラミング言語の相対的な力の正確な比較が得られることはほとんどないことを意味します。正確な比較は得られますが、正確な比較は得られません。特に、言語を比較する目的で明示的に行われた研究は、おそらく小さな問題を使用し、必然的に事前に定義された問題を使用するため、より強力な言語の力を過小評価する傾向があります。
現場からの報告は、「科学的」な研究ほど正確ではないにしても、より意味のあるものになる可能性があります。たとえば、エリクソン社のウルフ・ウィガーは、 研究を行い、ErlangはC++よりも4〜10倍簡潔であり、ソフトウェア開発の速度がそれに比例して速いという結論に至りました。
エリクソン社内の開発プロジェクト間の比較は、ソフトウェア開発のすべての段階を含め、使用された言語(Erlang、PLEX、C、C++、またはJava)に関係なく、同様の行/時間生産性を示しています。さまざまな言語を差別化するものは、ソースコードの量になります。
この研究では、ブルックスの著書では暗黙的であった点(彼はデバッグされたコードの行数を測定していたため)を明示的に扱っています。より強力な言語で書かれたプログラムは、バグが少ない傾向があります。それは、ネットワークスイッチなどのアプリケーションでは、プログラマーの生産性よりも重要になる可能性のある、それ自体が目的になります。
味覚テスト
最終的には、自分の直感を頼りにする必要があると思います。その言語でプログラミングするのはどんな感じですか?私は、最高の言語を見つける(または設計する)方法は、言語がどれだけうまく考えさせてくれるかに対して過敏になることだと思います。そして、最も良いと感じられる言語を選択/設計します。もし、言語の機能がぎこちなかったり、制限的だったりしたら、心配しないでください。あなたはそれを知っています。
そのような過敏症は、代償を伴います。あなたは、ぎこちない言語でプログラミングすることが耐えられないことに気づくでしょう。私は、マクロのない言語でプログラミングすることは、動的型付けに慣れている人が、すべての変数の型を宣言しなければならず、異なる型のオブジェクトのリストを作成できない言語でプログラミングに戻らなければならないことを耐えられないように感じるのと同じように、耐えられないほど制限的だと感じます。
私は一人ではありません。私は、多くのLispハッカーがそう感じていることを知っています。実際、プログラミング言語の相対的な力の最も正確な尺度は、その言語を知っている人のうち、アプリケーションドメインに関係なく、その言語を使用できる仕事ならどんな仕事でも引き受ける人の割合かもしれません。
制限
私は、ほとんどのハッカーは、言語が制限的であることを意味することを知っていると思います。あなたがそう感じるのは、どういうことでしょうか?それは、あなたが通りたい道が封鎖されていて、あなたが行きたい場所にたどり着くために長い迂回をしなければならないのと同じような感覚だと思います。あなたは言いたいことがあるのに、言語がそれを許してくれません。
私が思うに、ここで実際に起こっていることは、制限的な言語は、十分に簡潔ではないということです。問題は、あなたが計画していたことを言うことができないということだけではありません。言語があなたにさせる迂回が長いということです。この思考実験を試してみてください。あなたが書きたいプログラムがあり、言語があなたが計画していた方法でそれを表現することを許さず、代わりにあなたが計画していた方法よりも短い別の方法でプログラムを書くことを強制したとします。少なくとも私にとっては、それはあまり制限的ではないように感じます。それは、あなたが通りたい道が封鎖されていて、交差点にいる警官が迂回ではなくショートカットを指示しているようなものです。素晴らしい!
私は、ほとんど(90%?)の制限的な感覚は、言語で書くプログラムを、頭の中にあるプログラムよりも長くすることを強制されることから来ていると思います。制限は、ほとんどの場合、簡潔さの欠如です。 そのため、言語が制限的であると感じるときは、それは(ほとんどの場合)言語が十分に簡潔ではないことを意味し、言語が簡潔ではないときは、制限的であると感じます。
可読性
私が始めた引用では、規則性と可読性の2つの他の特性について言及しています。規則性とは何か、または規則的で可読性のあるコードが、単に可読性のあるコードよりもどのような利点があるのかはわかりません。しかし、可読性とは何かはわかっていると思いますし、それは簡潔さにも関連していると思います。
ここでは、個々のコード行の可読性と、プログラム全体の可読性を区別する必要があります。重要なのは後者です。Basicの1行はLispの1行よりも可読性が高い可能性があることに同意します。しかし、Basicで書かれたプログラムは、Lispで書かれた同じプログラムよりも多くの行を持つことになります(特に、Greenspunlandを超えると)。Basicプログラムを読むための合計労力は、間違いなく大きくなります。
合計労力 = 1行あたりの労力 x 行数
可読性が簡潔さに直接比例するとは確信していませんが、力は比例すると思います。しかし、確かに簡潔さは、可読性における要因(数学的な意味で、上記の式を参照)です。そのため、言語の目標が簡潔さではなく可読性であると言うことは、意味がないかもしれません。それは、目標が可読性ではなく可読性であると言うようなものです。
1行あたりの可読性が、初めて言語に出会うユーザーにとって意味するのは、ソースコードが脅威を感じさせないということです。そのため、1行あたりの可読性は、設計上の決定としては良くなくても、マーケティング上の決定としては良いかもしれません。それは、人々に分割払いをすることを許すという非常に成功したテクニックと同じです。高い前払い価格で人を怖がらせる代わりに、低い月々の支払いを伝えます。分割払いは、買い手にとって純粋な損失ですが、1行あたりの可読性も、プログラマーにとってはおそらくそうでしょう。 買い手は、それらの低価格の支払いをたくさん行うことになります。そして、プログラマーは、それらの個別に可読な行をたくさん読むことになります。
このトレードオフは、プログラミング言語よりも前に存在していました。小説や新聞記事を読むことに慣れている場合、数学論文を初めて読む経験は、落胆するかもしれません。1ページを読むのに30分かかったりします。 しかし、私は、表記が問題ではないと確信しています。たとえそう感じられるとしてもです。数学論文が読みづらいのは、アイデアが難しいからです。もし、同じアイデアを散文で表現していたら(数学者が簡潔な表記を進化させる前にそうしなければならなかったように)、論文は本のサイズにまで膨れ上がり、読みやすくなることはありません。
どの程度まで?
簡潔さ=力という考えを拒否した人はたくさんいます。それらが同じであるか、そうでないかを単に議論するのではなく、簡潔さはどの程度力に等しいのかを尋ねる方が有益だと思います。なぜなら、簡潔さは、高水準言語がのためにあるものの大きな部分を占めていることは明らかだからです。もし、それがすべてではないなら、それらは他に何のためにあり、これらの他の機能は、相対的にどれほど重要なのでしょうか?
私は、単に議論をより文明的にするためだけに、これを提案しているわけではありません。私は本当に答えを知りたいのです。言語が、自分自身にとってあまりにも簡潔になるのは、いつ、もしあれば、いつでしょうか?
私が始めた仮説は、病的な例を除いて、簡潔さは力とみなすことができるということでした。私が意味していたのは、誰もが設計する言語では、それらは同一になるだろうということですが、もし誰かがこの仮説を明確に反証するために言語を設計したいと思えば、おそらくできるだろうということです。実際、それさえ確信していません。
言語、プログラムではない
私たちは、個々のプログラムではなく、言語の簡潔さについて話していることを明確にする必要があります。個々のプログラムが、あまりにも密に書かれていることは、確かに可能です。
私は、On Lispでこれについて書きました。複雑なマクロは、正当化されるためには、それ自身の長さの何倍もの量を節約する必要があるかもしれません。もし、複雑なマクロを書くことで、使用するたびに10行のコードを節約でき、マクロ自体が10行のコードなら、1回以上使用すれば、行数の純粋な節約になります。しかし、それは依然として悪い動きである可能性があります。なぜなら、マクロの定義は、通常のコードよりも読みづらいからです。マクロが可読性の純粋な改善をもたらすまで、10回か20回はマクロを使用する必要があるかもしれません。
私は、すべての言語がそのようなトレードオフを持っていると確信しています(ただし、言語が強力になるにつれて、賭け金が高くなると思います)。すべてのプログラマーは、賢い人が疑わしいプログラミングトリックを使って、わずかに短くしたコードを見たことがあるはずです。
ですから、それについては議論はありません。少なくとも、私からは。個々のプログラムは、自分自身にとってあまりにも簡潔である可能性があります。問題は、言語はそうなることができるでしょうか?言語は、プログラマーに、全体的な可読性を犠牲にして、(要素の観点から)短いコードを書くことを強いることができるでしょうか?
言語が過度に簡潔であると想像しにくい理由の1つは、もし、何かを表現するための過度にコンパクトな方法があれば、おそらくより長い方法もあるからです。たとえば、Lispプログラムで、多くのマクロや高階関数が使用されているために、あまりにも密になっていると感じたら、好みに応じて、Pascalと同等のコードを書くことができます。もし、Arcで階乗を、高階関数の呼び出しとして表現したくないなら
(rec zero 1 * 1-)
再帰的な定義を書くこともできます。
(rfn fact (x) (if (zero x) 1 (* x (fact (1- x)))))
私は、すぐに思いつく例はありませんが、言語が過度に簡潔になる可能性があるという問題に興味があります。言語は、あなたがコードをぎこちなく、理解不能な方法で書くことを強制するでしょうか?もし、誰かが例を知っていたら、ぜひ見せてください。
(注意:私が探しているのは、上記の「要素」の指標に従って非常に密なプログラムであり、区切り文字を省略したり、すべてが1文字の名前を持つために短いプログラムではありません。)