簡潔さは力なり---Succinctness is Power---

Paul Graham, May 2002.
Copyright 2002 by Paul Graham.

これは、Paul Graham:Succinctness is Power を、原著者の許可を得て翻訳・公開するものです。

プロジェクト杉田玄白正式参加テキスト。

<版権表示>
本和訳テキストの複製、変更、再配布は、この版権表示を残す限り、自由に行って結構です。
(「この版権表示」には上の文も含まれます。すなわち、再配布を禁止してはいけません)。
Copyright 2002 by Paul Graham
原文: http://www.paulgraham.com/power.html
日本語訳:Shiro Kawai (shiro @ acm.org)
<版権表示終り>

Paul Graham氏のエッセイをまとめた『ハッカーと画家』の 邦訳版が出版されました。
出版社の案内ページ Amazon.co.jp サポートページ

2002/05/30 翻訳公開
2002/06/10 プロジェクト杉田玄白正式参加に伴い版権表示を整備


技術野郎の復讐---Revenge of the Nerds---に関して LL1メイリングリストで交わされた議論の中で、 Paul Prescodが書いた一文が私の心にひっかかった。

Pythonのゴールは正規性(regularity)と可読性(readability)であって、 簡潔さではない。
表面上の意味だけを取れば、プログラミング言語に関してこんな風に言うのは ずいぶんばかげたことのように思える。少なくとも私の理解するところでは、 簡潔さ=力、である。そうだとしたら、置換によって次の文が得られる。
Pythonのゴールは正規性(regularity)と可読性(readability)であって、 力ではない。

そうだとしたら、これはあまり良い取り引きではなさそうだ。 だってこれじゃまるで、Pythonのゴールはプログラミング言語として有効ではなくなることだ と言っているようなものだからだ。

では、本当に簡潔さ=力なのだろうか。これは私にとっては重要な問いだ。 多分、言語を設計する人にとって最も重要な問いだし、だから真向から取り組むことは 有意義だろう。私は、まだその答えが単純なイエスであるとは確信できないが、 最初の仮定としては良いもののように思える。

仮定

私の仮定は、簡潔さは力であるか、もしくは病的な例を除けば 両者は同一とみなせる程近い、というものだ。

私にとっては、簡潔さこそがプログラミング言語の存在理由だ。 コンピュータは直接機械語でやることを命令されたって意に介さない。 なのにわざわざ高レベル言語を設計する手間をかけるのは、 それによって梃の力を得るからだ。高級言語を使えば、1000行の機械語を要することを 10行で書き表せる(し、より重要なことに、考えることができる)。 言い替えれば、高レベル言語を作る主要な理由はソースコードを小さくすることだ。

小さなソースコードが高レベル言語の目的であり、 力がその目的をどれだけうまく達成できるかというものなら、 プログラミング言語の力を測るには、 それがプログラムをどれだけ小さくできるかを見ればよいということになる。

逆に、言語がプログラムを小さくしないのなら、それはプログラミング言語の役割を ちゃんと果たしていないということだ。切れないナイフとか、 読めない印刷とかと同じだ。

指標

でも、「小さい」っていうのは一体どういう意味においてだ? いちばん広く使われるコードサイズの指標はコードの行数だ。 でもこの指標は単に測るのがいちばん簡単だというだけで使われているんだと思う。 誰も、プログラムの長さを測るのに行数が一番だなんて思っちゃいないだろう。 言語が異なれば、一行あたりに通常書く情報というものが違って来る。 Cではたくさんの行には、ひとつかふたつのデリミタがあるだけだ。

もうひとつの簡単なテストはプログラムの文字数だが、 これもあまりよくない。いくつかの言語(例えばPerl)は他の言語より 短い識別子を用いている。

私が考える、プログラムのサイズを測る良い指標は、その要素数だ。 ここで要素とは、ソースコードをツリーで表現したときに別々のノードに なるものとする。変数や関数の名前は要素だ。 整数や浮動小数点数も要素だ。リテラルテキストも要素だし、 パターン中の要素やフォーマット指示子なんかも要素として数えられる。 新しいブロックも要素だ。境界的な場合 (-5は2つの要素か1つか?) はあるが、 そういうのは大抵の言語で似たりよったりだと思うから、 比較にはあまり影響を与えないだろう。

この指標はもっと明確化する必要があるし、 それぞれの言語毎にちゃんと解釈する必要があるが、 正しいものを測ろうとしていると私は思う。 つまり、プログラムの持つ部品の数だ。 この練習であなたが書く木は、まさにそのプログラムを理解するときに頭の中に 描かれるものだ。だからそのサイズはそれを書いたり読んだりする手間に正比例する。

設計

この種の指標によって我々は異なる言語を比較することができるようになるが、 それは主要な価値ではない。少なくとも私にとってこのような簡潔さの指標を持つことの 主要な価値は、言語を設計する際のガイドとして使えるということだ。 最も有用な言語の比較とは、一つの言語の可能な二つの変化形があり得る時に それらを比較することだ。どう言語をいじればプログラムを短くできるだろう?

プログラムの認知的な負荷がその複雑さに比例し、 プログラマが耐えられる認知的な負荷が一定だとしたら、 上の問いは、どうすればプログラマにより多くの仕事が出来ようにするか、と問うに等しい。 そして私にとってはその問いは、どうやったら良い言語が設計できるか、 というのと等価である。

(言語を設計するという行為は、 「全ての言語は等価である」といういにしえの言い伝えは嘘だと悟るのに 最適な方法だ。新しい言語を設計するとき、あなたは常に 二つの言語---機能xをつけた言語と、つけない言語---を比較して、 どちらが優れているかを判断し続けている。 これが意味のない問いならば、そんなことはコインを投げて決めれば良い。)

簡潔さを目指すのは、新しいアイディアを見付ける良い方法だ。 ある方法でたくさんの異なるプログラムを短くできることを思い付いたとしたら、 それはただの偶然じゃなくて、たぶん新しい抽象化の方法を発見したんだ。 ソースコードから繰り返し起こるパターンを探すプログラムを書くことさえ できるかもしれない。良いアイディアを探したければ、 たくさんの言語のうち、簡潔さで名高い言語を調べると良いだろう:Forth, Joy, Icon等だ。

比較

私の知る限り、この問題について最初に書いたのはFred Brooksだ。 彼は「人月の神話」の中で、平均的なプログラマが生産できるコードの行数は 言語によらずほぼ一定であると述べていたと思う。 私は確か、学部生か大学院に入りたての頃にそれを読んで新鮮な驚きを受け、 その意味するところは非常に大きいと感じた。 だってそこから得られる結論は、 (a) ソフトウェアをより速く書く唯一の方法は より簡潔な言語を使うことで、 (b) その手間を掛けた者はそうしなかった競争相手を はるか後方に引き離すことが出来る、ってことだからだ。

Brookの観察は、それが真実なら、ハッキングの中心にあるものだと思える。 以来ずっと私は、正当な研究から個々のプロジェクトにおける逸話まで、 この問いに対する証拠が得られないかどうかに気を配って来た。 今までのところ、彼の主張に矛盾することは見たことがない。

私はまだこの問いに決着を付けられるような確たる証拠は見ていない。 多分そういうものは見つからないだろう。Lutz Precheltのプログラミング言語の 比較みたいな研究は私が期待するような結果を出しているが、 意味のあるテストとするには短すぎる問題を使いがちだ。 言語のより良いテストは書くのに1ヵ月かかるようなプログラムにおいて 何が起こるかを見ることだ。 あなたが私と同じように、 言語の主要な目的はその言語によってものごとを考えやすくすることだ (考えた後でコンピュータにその手順を教えやすいかどうかではなく) ということを信じるならば、 唯一の本物のテストはその言語によってどんな新しいことが書けるか、ということになる。 だから、あらかじめ決められた仕様に合わせてコードを書くという形式の 言語間の比較は、少し的を外している。

言語の真のテストはどれだけうまく新しい問題を発見できて解けるかにあり、 その言語を使って誰かが既に定式化した問題を解けるかどうかには無い。 この二つは全然違う基準だ。芸術では、刺繍やモザイクといったメディアは 何を作るかをあらかじめ知っていればうまくいくが、そうでなければめちゃくちゃになる。 作りながらイメージを発見したいのなら---例えば人物画のような複雑なイメージを 扱いたい時はほとんどそうなのだが---もっと柔軟性のあるメディア、 鉛筆とかインク・ウオッシュ、あるいは油彩が必要だろう。 実際、タペストリーやモザイクは最初に画を描いてからそれをコピーすることで作られている。 (「cartoon」という単語はもともとはこの目的で描かれる画を指す言葉だった)。

そうだとしたら、プログラミング言語間の相対的な力を正確に比べるのは まず不可能だということになる。 精度の高い比較は出来るかもしれないが、決して正確にはならない。 特に、言語を比較することを目的に掲げた研究ではそうだ。 そういう研究は小さな問題を使うだろうし、 何よりあらかじめ定義されている問題を使わざるを得ないのだから、 よりパワフルな言語の力を過小評価しがちになる。

現場からの報告は、「科学的な」研究よりは精度が劣らざるを得ないが、 意味のあるものである可能性は高い。例えばEricssonでUlf Wigerがやった 研究では、 ErlangはC++より4〜10倍簡潔で、それに比例して速く開発ができたと結論づけている:

Ericsson内部の開発プロジェクト間の比較によれば、 ソフトウェア開発の全ての段階において 使用言語(Erlang, PLEX, C, C++, Java)の如何にかかわらず、 時間当たりの開発行数は似たような数値となった。 言語間の差が出たのはソースコードの量だった。

この研究はまた、Brooksの本では暗示されていただけだった点 も明示的に扱っている (彼はデバッグされるコードの行数を測った): よりパワフルな言語で書かれたプログラムにはバグが少ない。 ネットワークスイッチのようなアプリケーションでは、この事実は決定的だ。 プログラマの生産性よりも重要だろう。

センス

突き詰めてゆくと、最後は自分の腹の底で判断せざるを得ないだろう。 その言語でプログラムを書くときにどんな感じがするか。 最良の言語を見付ける(そして設計する)方法は、その言語でどれだけうまく考えられるか という点に過敏になることだと思う。そうしておいて、一番いい感じの言語を選ぶか 設計するかするんだ。もし言語にぎこちなかったり制限のある機能があったとしたら、 大丈夫、いずれわかるから。

このような過敏性にはデメリットもある。 もはや、できの悪い言語でプログラミングするのに耐えられなくなるのだ。 私はもはやマクロの無い言語では縛りがきつすぎて耐えられない。 ちょうど、動的型付けに慣れたプログラマが、 全ての変数の型を宣言しなくちゃならなくて、 型の異なるオブジェクトのリストを作れないような言語の制限に耐えられないと 感じるのと一緒だ。

これは私だけではない。同じように感じているLispハッカーをたくさん知っている。 もしかすると、プログラミング言語の相対的な力を測る正確な指標は、 その言語を知っている人々のうちで、アプリケーション領域にかかわらずとにかくその言語が 使えるならどんな仕事でも受ける、という人々の割合を測ることかもしれない[訳註1]

制限

大抵のハッカーは、言語に制限がきついと感じるというのはどういうことか わかるんじゃないかと思う。そう感じたとき何が起こっているのだろう。 進もうとしてた道路が封鎖されてて、 行きたいところに行くために長い回り道をしなくちゃならなかった時の感じ、 あれとそっくりだと私は思う。 言いたいことがあるのに、言語がそれを言わせてくれないんだ。

ここで起きているのは、制限のある言語は十分に短くないということだ。 言おうと思っていることが言えないというだけが問題ではない。 言語に強制される回り道が長いというのが問題なんだ。 こんな思考実験をしてみたまえ。 書きたいプログラムがあったとして、 言語がそれを思った通りには表現させてくれなかったけど、 それより短いやりかたで書くのを強制されたとしよう。 少なくとも私にとって、そういう言語は強い制限があるようには感じないだろう。 それはまるで通ろうと思っていた道路が封鎖されてて、交差点にいたお巡りさんが 回り道の代わりに近道を教えてくれたようなものだ。素晴らしいじゃないか。

制限されているという感覚の大部分 (90%?) は、その言語では 頭の中に描いたものよりも長く書くことを強制されているからだと私は思う。 制限は、大部分は簡潔さの欠如だ。 言語に制限がきついと感じたら、それは(大部分は)十分に簡潔でないということだし、 言語が簡潔でないなら、制限が強いと感じることだろう。

可読性

私が最初に引用した文では他に2つの質が述べられていた。正規性(regularity)と 可読性(readability)だ。正規性が正確に何を意味しているのか、 また正規でかつ読みやすいコードというのがあったとして、それがただ読みやすいコード に比べてどれだけ良いのか、私にはよくわからない。 ただ、可読性については分かるし、私はそれも簡潔さに関連していると思う。

ここで、コードの各行の可読性とプログラム全体の可読性との違いに 注意しておかねばならない。必要なのは後者だ。Basicの一行はたぶんLispの一行より 読みやすいだろう。だが、Basicで書かれたプログラムにはLispで書かれた同じプログラム よりもたくさんの行があるだろう (特に、グリーンスパン国の領域に入ってしまったら)。 当然、Basicプログラムを読むトータルの苦労は大きくなる。

苦労の合計 = 各行を読む苦労 × 行数

力が簡潔さと直接比例しているのと同じくらい可読性が簡潔さと比例しているか どうかは定かではないが、確かに簡潔さは可読性のファクターである (数学的な意味でだ; 上の等式を見たまえ)。だから、言語のゴールは簡潔さでなく可読性だというのは 意味の無いことかもしれない。それは、ゴールは可読性ではなく可読性だと言っているような ものだからだ。

行当たりの可読性が良いと、 ユーザが最初に言語に出会った時に、ソースコードがおっかなく見えない。 だから行当たりの可読性は、設計上の決断としてはだめかも しれないが、マーケティングの決断としては良いかもしれない。 これは月賦販売という非常に成功したテクニックと同型だ。 一度にたくさん払うことで恐がらせるのではなく、毎月少しづつ払わせることで 安心させるのだ。しかし、月賦は常に合計では買い手の損になるし、 単なる行当たりの可読性は常にプログラマの損失になる。 買い手は少ない支払をたくさんすることになるだろう。 そしてプログラマは一行一行は読みやすいプログラムのたくさんの行を 読むことになるだろう。

このようなトレードオフはプログラミング言語以前からあった。 小説や新聞記事を読み慣れた人が最初に数学の論文を読んだらうろたえることだろう。 1ページ読むのに30分かかるかもしれない。 最初は表記法のせいだと思うかもしれないけれど、そうじゃないんだ。 数学の論文を読むのが難しいのは、そこに示されている考えが難しいからだ。 同じ考えを散文で書いたとしても(それが、簡潔な表記法が発明される前に数学者達が 取らざるを得なかった表記だった)、読むのが簡単にはならないだろう。 その論文は多分本一冊の分量になるだろうから。

程度

たくさんの人が、簡潔さ=力という考えを拒否した。 でも、両者が等しいか等しくないかを議論するより、 どの程度まで簡潔さは力と等しいのか、を考えた方が有用だと思う。 だって簡潔さというのは明らかに高レベル言語の目的の大きな部分なんだから。 それが全部でないんだとしたら、残りの目的は何だろう、 そして他の機能と比べてどのくらい重要なんだろう。

このディベートを文明的にするためにこんな提案をしてるんじゃない。 本当に答えた知りたいんだ。言語は、必要以上に簡潔に成り得るのか、成り得るとしたら どんなときか。

私が最初に置いた仮定は、病的な例を除いては、簡潔さは力と考え得るんじゃないか というものだった。私が言いたかったのは、誰が設計する言語においても両者は 等しくなるだろうけど、もしこの仮定を否定するためだけに言語を設計しようとすれば できるかもしれないということだ。ただ、実際にそれが可能かどうか、私にはわからない。

言語なり、プログラムにあらず

我々は言語の簡潔さを問題にしているのであって、個々のプログラムの短さではない ことをはっきりさせておかねばならないだろう。 個々のプログラムが過度に濃密であることは当然あり得る。

このことはOn Lisp で書いた。複雑なマクロは、それ自体は長くても、その何倍ものコードを節約できる。 使う度に10行節約できる、ごちゃごちゃしたマクロを書いたとしよう。 そのマクロの定義自体に10行使うとする。すると、そのマクロを2回以上使えば、 全体の行数は小さくなる。でもそれはたぶんうまくない方法だ。 マクロ定義は通常のコードより読むのが難しいからだ。 10回か20回使うようなマクロじゃないと、 全体の可読性は向上しないだろう。

どんな言語にも、そういうトレードオフはある (ただ、言語がパワフルになればなるほどその問題は大きくなるだろうが)。 どんなプログラマも、だれか賢い人が怪しいプログラミングトリックを使って ほんのちょっと短くしたコードを見たことがあるだろう。

だからここには議論は無いと思う---少なくとも私からは。 個々のプログラムは確かに必要以上に短くなり得る。 問題は、言語がそうなるかどうかだ。 言語がプログラマをして、全体の可読性を損なうほど(要素数で)短く書くことを強いるような ことがあるだろうか。

簡潔すぎる言語というのを想像するのが難しい理由の一つは、 もし何かを非常にコンパクトに表現する方法があったとしても、 多分それより長く表現する方法もあるだろうからだ。 例えばたくさんのマクロや高階関数を使うのが濃すぎると感じたら、 Pascalと同じようにだって書ける。 Arcで階乗を高階関数で次のように書きたくなければ:

(rec zero 1 * 1-)

つぎのような再帰的な表記を使っても良い:

(rfn fact (x) (if (zero x) 1 (* x (fact (1- x)))))

私は例をすぐに思い付けないけれど、言語が簡潔すぎることが可能かどうかという問いには 興味がある。ごちゃごちゃ固まって理解不能なようにしかコードを書けないような 言語なんてあるだろうか。誰か例を思い付いたら、是非見てみたい。

(注意:私が探しているのは上で述べた「要素数」の指標で非常に濃密なプログラム であって、デリミタが省略されたり全てに一文字の名前を使ったりして短くしている コードではない)。


関連するリンク


訳註

訳註1
訳註でないけれど、さすがにここは訳してて突っ込みたくなったんで。 この事実からなら、Lispは中毒性が高いだけだという結論も導けるよなあ。

[Practical Scheme]