簡潔さは力なり

簡潔さは力なり

説明: 「代数的記号によって狭い空間に圧縮された意味の量は、私たちが慣れ親しんでいる推論を促進するもう一つの状況です...」

2002年5月

| 「代数的記号によって狭い空間に圧縮された意味の量は、私たちが慣れ親しんでいる推論を促進するもう一つの状況です...」

  • Charles Babbage, Iversonのチューリング賞受賞講演より引用

Revenge of the Nerdsによって提起された問題に関するLL1メーリングリストでの議論で、Paul Prescodが私の心に留まることを書きました。

Pythonの目標は、簡潔さではなく、規則性と可読性です。

一見すると、これはプログラミング言語についてかなり痛烈な主張のように思えます。私が知る限り、簡潔さ = 力です。もしそうなら、代入すると、

Pythonの目標は、力ではなく、規則性と可読性です。

そして、これは(もしそれがトレードオフであるなら)あなたがしたいと思うトレードオフではないように思えます。Pythonの目標は、プログラミング言語として効果的であることではないと言っているのと大差ありません。

簡潔さ = 力なのでしょうか?これは私にとって重要な問題であり、言語設計に関心のある人にとってはおそらく最も重要な問題であり、直接向き合うことが有益でしょう。まだ答えが単純なイエスであるとは確信していませんが、まずは良い仮説のように思えます。

仮説

私の仮説は、簡潔さが力である、または病的な例を除いて、それらを同一のものとして扱えるほど近いということです。

私にとって、簡潔さはプログラミング言語の_目的_であるように思えます。コンピュータは、機械語で直接指示されることにも同じように満足するでしょう。高水準言語を開発する主な理由は、レバレッジを得て、機械語で1000行必要になることを高水準言語で10行で言う(そしてより重要なことに、考える)ことができるようにするためだと思います。言い換えれば、高水準言語の主な目的は、ソースコードを小さくすることです。

もし小さいソースコードが高水準言語の目的であり、何かの力がその目的をどれだけうまく達成するかであるなら、プログラミング言語の力の尺度は、プログラムをどれだけ小さくするかです。

逆に、プログラムを小さくしない言語は、うまく切れないナイフや判読できない印刷物のように、プログラミング言語がすべきことをうまく実行していません。

指標

しかし、どのような意味で小さいのでしょうか?コードサイズの最も一般的な尺度は、コード行数です。しかし、この指標が最も一般的なのは、測定が最も簡単だからだと思います。プログラムの真の長さを本当に信じている人はいないと思います。言語によって、1行にどれだけ記述するかの慣習が異なります。C言語では、多くの行には区切り文字が1つか2つしかありません。

別の簡単なテストは、プログラム内の文字数ですが、これもあまり良くありません。一部の言語(たとえば、Perl)は、他の言語よりも短い識別子を使用するだけです。

プログラムのサイズのより良い尺度は、要素の数だと思います。要素とは、ソースコードを表すツリーを描いた場合に、個別のノードになるものです。変数または関数の名前は要素です。整数または浮動小数点数は要素です。リテラルテキストのセグメントは要素です。パターンまたは書式指定子の要素は要素です。新しいブロックは要素です。境界線上のケース(-5は2つの要素ですか、それとも1つですか?)がありますが、それらのほとんどはすべての言語で同じであるため、比較に大きな影響を与えないと思います。

この指標は肉付けが必要であり、特定の言語の場合には解釈が必要になる可能性がありますが、プログラムが持つ部分の数を測定しようとしていると思います。この演習で描くツリーは、プログラムを考案するために頭の中で作成する必要があるものであり、そのサイズは、それを書いたり読んだりするために行う必要がある作業量に比例すると思います。

設計

この種の指標を使用すると、異なる言語を比較できますが、少なくとも私にとっては、それが主な価値ではありません。簡潔さテストの主な価値は、言語を_設計_する際のガイドとしてです。言語間の最も有用な比較は、同じ言語の2つの潜在的なバリアント間の比較です。プログラムを短くするために、言語で何ができますか?

プログラムの概念的な負荷がその複雑さに比例し、特定のプログラマーが固定された概念的な負荷に耐えることができる場合、これは、プログラマーが最大限に成果を上げるために何ができるかを尋ねるのと同じです。そして、それは私にとって、どのように優れた言語を設計できるかを尋ねるのと同じです。

(ちなみに、古い決まり文句「すべての言語は同等である」が誤りであることをこれほど明白にするものはありません。新しい言語を設計するとき、あなたは_常に_2つの言語、つまりxを実行した場合の言語と実行しなかった場合の言語を比較して、どちらが良いかを判断しています。これが本当に意味のない質問である場合、コインを弾くのと同じです。)

簡潔さを目指すことは、新しいアイデアを見つけるための良い方法のように思えます。多くの異なるプログラムを短くすることができる何かを実行できる場合、それはおそらく偶然ではありません。おそらく、有用な新しい抽象化を発見したのでしょう。ソースコードで繰り返されるパターンを検索することで、プログラムを作成して支援することもできます。他の言語の中でも、簡潔さで定評のある言語は、新しいアイデアを探すのに適しています:Forth、Joy、Icon。

比較

私が知る限り、これらの問題について最初に書いたのは、Fred Brooksの_Mythical Man Month_でした。彼は、プログラマーは言語に関係なく、1日にほぼ同じ量のコードを生成するように見えると書いています。20代前半にこれを初めて読んだとき、それは私にとって大きな驚きであり、大きな意味があるように思えました。それは、(a)ソフトウェアをより速く記述する唯一の方法は、より簡潔な言語を使用することであり、(b)これを行う手間をかけた人は、そうしなかった競合他社を置き去りにすることができることを意味しました。

Brooksの仮説が真実であれば、ハッキングの中心にあるように思えます。それ以来、私はこの問題に関する証拠を入手するために、正式な研究から個々のプロジェクトに関する逸話まで、細心の注意を払ってきました。彼に反論するものは何も見ていません。

まだ決定的な証拠を見たことはなく、期待もしていません。Lutz Precheltのプログラミング言語の比較のような研究は、私が期待した種類の結果を生成しますが、意味のあるテストを行うには短すぎる問題を使用する傾向があります。言語のより良いテストは、記述に1か月かかるプログラムで何が起こるかです。そして、言語の主な目的は、(考えた後でコンピュータに指示するだけでなく)考えるのに適していることだと信じているなら、唯一の真のテストは、それで何ができるかです。したがって、定義済みの仕様を満たす必要のある言語比較は、わずかに間違ったことをテストしています。

言語の真のテストは、新しい問題を発見して解決できるかどうかであり、他の誰かがすでに定式化した問題を解決するためにそれを使用できるかどうかではありません。これら2つはまったく異なる基準です。芸術では、刺繍やモザイクのような媒体は、何を作りたいかを事前に知っている場合はうまく機能しますが、そうでない場合はまったくひどいです。イメージを作成するときにイメージを発見したい場合(たとえば、人物のイメージのように複雑なもので行う必要がある場合)、鉛筆、墨絵、油絵などのより流動的な媒体を使用する必要があります。そして実際、タペストリーやモザイクが実際に作られる方法は、最初に絵を描き、それをコピーすることです。(「漫画」という言葉は、もともとこの目的のために描かれた絵を指すために使用されていました)。

これは、プログラミング言語の相対的な力を正確に比較できる可能性が低いことを意味します。正確な比較はできますが、正確な比較はできません。特に、言語を比較する目的で行われる明示的な研究は、おそらく小さな問題を使用し、必然的に定義済みの問題を使用するため、より強力な言語の力を過小評価する傾向があります。

現場からの報告は、必然的に「科学的な」研究よりも精度が低くなりますが、より意味がある可能性があります。たとえば、EricssonのUlf Wigerは、ErlangがC ++よりも4〜10倍簡潔であり、ソフトウェアの開発が比例して速いという研究を行いました。

Ericsson社内の開発プロジェクト間の比較は、ソフトウェア開発のすべての段階を含め、どの言語(Erlang、PLEX、C、C ++、またはJava)が使用されたかに関係なく、同様の行/時間生産性を示しています。異なる言語を区別するものは、ソースコードのボリュームです。

この研究はまた、Brooksの本で暗黙的にしか扱われていなかった点(彼はデバッグされたコードの行数を測定したため)を明示的に扱っています。より強力な言語で記述されたプログラムは、バグが少ない傾向があります。これは、ネットワークスイッチのようなアプリケーションでは、プログラマーの生産性よりもおそらく重要な、それ自体が目的になります。

味覚テスト

最終的には、直感に従う必要があると思います。その言語でプログラミングするのはどんな感じですか?最高の言語を見つける(または設計する)方法は、言語がどれだけうまく考えさせてくれるかに非常に敏感になり、次に最も気持ちの良い言語を選択/設計することだと思います。言語機能が扱いにくいか制限的である場合は、心配しないでください。あなたはそれについて知ることになります。

そのような過敏症には代償が伴います。あなたは、不器用な言語でプログラミングすることを_我慢できない_ことに気づくでしょう。マクロのない言語でプログラミングすることは耐え難いほど制限的だと感じます。動的型付けに慣れている人が、すべての変数の型を宣言する必要があり、異なる型のオブジェクトのリストを作成できない言語でプログラミングに戻るのが耐え難いほど制限的だと感じるのと同じです。

そう思っているのは私だけではありません。私は多くのLispハッカーがこれに遭遇したことを知っています。実際、プログラミング言語の相対的な力の最も正確な尺度は、その言語を知っている人のうち、アプリケーションドメインに関係なく、その言語を使用できる仕事なら何でも引き受ける人の割合かもしれません。

制限

ほとんどのハッカーは、言語が制限的に感じるとはどういう意味かを知っていると思います。あなたがそれを感じるとき、何が起こっているのですか?それは、あなたが通りたい通りが封鎖されていて、行きたい場所に行くために長い迂回をしなければならないときに感じるのと同じ気持ちだと思います。言いたいことがあるのに、言語がそれを許してくれません。

ここで実際に起こっているのは、制限的な言語は十分に簡潔ではない言語だと思います。問題は、計画したことを言えないということだけではありません。言語があなたにさせる迂回が_より長い_ということです。次の思考実験を試してください。書きたいプログラムがあり、言語が計画した方法でそれを表現させてくれず、代わりにプログラムを_より短い_別の方法で書くことを強制するとします。少なくとも私にとっては、それはあまり制限的に感じません。それは、通りたい通りが封鎖されていて、交差点の警官が迂回ではなくショートカットに案内してくれるようなものです。素晴らしい!

制限感のほとんど(90%?)は、頭の中にあるものよりも言語で書くプログラムを長くすることを強制されることから来ていると思います。制限は主に簡潔さの欠如です。したがって、言語が制限的に感じるとき、それは(ほとんどの場合)十分に簡潔ではないことを意味し、言語が簡潔でない場合、それは制限的に感じられます。

可読性

私が最初に引用した引用は、規則性と可読性という他の2つの品質について言及しています。規則性が何であるか、または規則的で読みやすいコードが単に読みやすいコードよりも優れているかどうかはわかりません。しかし、可読性とはどういう意味かを知っていると思います。そして、それは簡潔さとも関係があると思います。

ここでは、個々のコード行の可読性とプログラム全体の可読性を区別するように注意する必要があります。重要なのは2番目です。Basicの行は、Lispの行よりも読みやすい可能性が高いことに同意します。しかし、Basicで記述されたプログラムは、Lispで記述された同じプログラムよりも多くの行を持つことになります(特にGreenspunlandに足を踏み入れた場合)。Basicプログラムを読むための総労力は、確かに大きくなるでしょう。

総労力 = 1行あたりの労力 x 行数

力が簡潔さに直接比例すると確信しているほど、可読性が簡潔さに直接比例するとは確信していませんが、簡潔さは確かに可読性の要素です(数学的な意味で、上記の式を参照)。したがって、言語の目標は簡潔さではなく可読性であると言うことは、可読性ではなく可読性であると言うのと同じように、意味がないかもしれません。

可読性/行が意味することは、言語に初めて遭遇するユーザーにとって、ソースコードが_脅威的に見えない_ということです。したがって、可読性/行は、設計上の決定が悪くても、優れたマーケティング上の決定になる可能性があります。それは、人々が分割払いで支払うことを許可するという非常に成功した手法と同型です。高額な前払い価格で彼らを怖がらせる代わりに、あなたは彼らに低い月々の支払いを伝えます。分割払いプランは、購入者にとっては純損失ですが、単なる可読性/行はおそらくプログラマーにとってはそうです。購入者は、それらの低い、低い支払いを_たくさん_行うことになります。そして、プログラマーは、個別に読みやすい行を_たくさん_読むことになります。

このトレードオフは、プログラミング言語よりも前から存在していました。小説や新聞記事を読むことに慣れている場合、数学論文を読む最初の経験は落胆する可能性があります。1ページを読むのに30分かかることがあります。それでも、表記法が問題ではないと確信しています。そう感じられるかもしれませんが。数学論文が読みにくいのは、アイデアが難しいからです。同じアイデアを散文で表現した場合(数学者が簡潔な表記法を進化させる前にそうする必要があったように)、論文が本のサイズに拡大するため、読みやすくなることはありません。

どの程度まで?

多くの人が、簡潔さ = 力という考えを拒否しています。それらが同じであるかそうでないかを単に議論するのではなく、簡潔さは_どの程度まで_力であるかを尋ねることがより有益だと思います。なぜなら、簡潔さは明らかに高水準言語の大きな部分を占めているからです。それがすべてではない場合、他に何のためにあり、これらの他の機能は相対的にどの程度重要ですか?

私は単に議論をより文明的にするためにこれを提案しているわけではありません。私は本当に答えを知りたいのです。言語がそれ自体にとって簡潔すぎるのはいつですか?

私が最初に立てた仮説は、病的な例を除いて、簡潔さは力と同一と見なすことができると考えているということでした。私が意味したのは、誰もが設計する言語では、それらは同一になるだろうということですが、誰かがこの仮説を明示的に反証するために言語を設計したい場合、おそらくそうすることができるでしょう。実際、それさえ確信していません。

言語、プログラムではなく

個々のプログラムではなく、言語の簡潔さについて話していることを明確にする必要があります。個々のプログラムが過度に密集して記述されることは確かに可能です。

私はOn Lispでこれについて書きました。複雑なマクロは、正当化されるために、それ自体の長さの何倍も節約する必要があるかもしれません。厄介なマクロを記述することで、使用するたびに10行のコードを節約でき、マクロ自体が10行のコードである場合、それを複数回使用すると、行数で正味の節約が得られます。しかし、マクロ定義は通常のコードよりも読みにくいため、それは依然として悪い動きになる可能性があります。可読性で正味の改善が得られるまで、マクロを10回または20回使用する必要があるかもしれません。

すべての言語にそのようなトレードオフがあると思います(ただし、言語がより強力になるにつれて、賭け金が高くなると思います)。すべてのプログラマーは、賢い人が疑わしいプログラミングトリックを使用してわずかに短くしたコードを見たことがあるはずです。

したがって、それについては議論の余地はありません。少なくとも私からは。個々のプログラムは、それ自体にとって簡潔すぎる可能性があります。問題は、言語がそうなる可能性があるかどうかです。言語は、プログラマーに全体的な可読性を犠牲にして、短い(要素の)コードを書くことを強制できますか?

言語が簡潔すぎることを想像するのが難しい理由の1つは、何かを過度にコンパクトに表現する方法がある場合、おそらくより長い方法もあるだろうということです。たとえば、多くのマクロまたは高階関数を使用するLispプログラムが過度に密集していると感じた場合は、必要に応じて、Pascalと同型のコードを記述できます。高階関数(rec zero 1 * 1-)への呼び出しとしてArcで階乗を表現したくない場合は、再帰的な定義(rfn fact(x)(if(zero x)1(* x(fact(1- x))))))を記述することもできます。頭の中で例を思いつくことはできませんが、言語が簡潔すぎる可能性があるかどうかという問題に関心があります。ぎこちなく理解できない方法でコードを書くことを強制する言語はありますか?例があれば、ぜひ見てみたいです。

(リマインダー:私が探しているのは、上記の「要素」の指標に従って非常に密集しているプログラムであり、区切り文字を省略でき、すべてに1文字の名前が付いているために短いだけのプログラムではありません。)

このページについて