ポール・グレアムの「Arcに挑戦」を翻訳しました。なお翻訳にあたってttamo様、ほんのしおり様、Gemma様、so-asano様のアドバイスを受けています。ありがとうございます

原題は"Take the Arc Challenge"で、原文は以下です。
http://www.paulgraham.com/arcchallenge.html

Arcに挑戦

2008年2月

Arcを公開して数日たった。みんなArcについて言いたいことがあるようだ。レベルの低い意見は、他の何に関することであれネット上のレベルの低い意見と同様だ。最高の意見はまだないが、Arcでのプログラミングがどういうものかについて経験から語れるようになるほどの時間がまだないからだと思う。それこそが聞きたかった意見なのだけれど。だが一方、ややまともな層の意見もある。問題を一応、理解しているが、第一印象に基づいて書く人々の意見だ。

私は不思議な共通点に気づいた。彼らがArcの主な欠点と思うのは、私がArcを書く際に、やるべき苦労を回避したように見える、ってことなのだ。 Ron Garretはこう言う。



それがArcに対する私の主な不満だ。Arcの製作期間はすごく長く、非常に高い目標を設定した。なのに言語設計の難しい問題のほとんどを回避しているように思える。




いつもの私は批判に直接、反論しない。反論を書くほうは楽しいが、読むほうはそうでもないからだ。だがこの場合は、Ronとその賛同者は他の人の参考になる間違いをしているので、反論しておこう。なぜなら誤解の理由を説明することによって言語デザインに関するいくつかの重要な問題がはっきりするからだ。

Ronは正しい。私は取り組む問題を、その問題の難しさで決めてはいなかった。そのかわり、かなりつまらないと思うかもしれないテストを使った。プログラムがすこしでも短くなるよう努力したのだ。

どうして? 高級言語はプログラムを短くするためにあるからだ。プログラミング言語の力はその言語で書かれたプログラムの長さに反比例すると言うのは、100%正確ではないかもしれないが、それに限りなく近い。誰かが次のように言ったら、どれくらいめちゃくちゃに聞こえるか想像して欲しい。「このプログラムは私の言語では50行だが、あなたの言語では10行だ。だが私の言語のほうが強力だ」あなたはこう考えるだろう・・・奴の言ってる「力」って何なの?

力がプログラミング言語を判断する唯一の基準だと言ってるんじゃない。たとえば子供が学びやすいとか、(昔ほど一般的な目標ではないが)効率的にコンパイルできるとか、グループ内のダメなプログラマによる被害を抑えるとかいう言語の設計も立派な目標だろう。だが、そういった特殊な目的のために設計された言語以外に対しては力こそが試金石となる。

だから、『実装が困難なことに努力を傾けるより、プログラムを短くすることに努力する』とは、言いかえればこういうことだ。



私はどの作業をするかは、自分の労力ではなくユーザにもたらす価値に基づいて選んだ。




これはプログラミング言語に限らず、他の人に使ってもらうことを目的としたものを設計する時には何であれ、確実に正しい優先順位のつけかただ。

私がした仕事がどれも容易だったということではない。困難に思える仕事もあった。だが言語の設計においては、困難か容易かにかかわらず、問題の解決はゴールではない。ゴールはよい言語を作ることだ。Arcやその他、汎用の高級言語の真価を測るテストは、特徴xがあるとか問題yを解決しているとかではなく、それで書いたプログラムがどれほどの長さになるかということだ

ユーザが実際に書くことになるプログラムこそ、より短くなるべきだ。したがってArcを作っていたときの私の方法論は、Arcでアプリケーションを書き、それをもっと短くできそうな機能が思い浮かばないかと1行ごとに見回すというものだった。その後、そうした機能を実装し、その機能を使ってプログラムを書き直して、やり直す。以下にHacker Newsのソースのコメントを示す。私がときどき記録していたものだ。(機能を追加したせいで、数字はたまに増えている)




; results of (codetree "news.arc"):
; 8787, 8760, 8738, 8726, 8823, 8755, 8703, 8628, 8587, 8565
; 8633, 8573, 8552, 8520, 8510, 8498, 8549, 8515, 8684, 9025
; 9573, 12196, 12469, 12648, 12373




ちなみに、Arc本体のソースコードがこんなに短くなってしまった理由もここにある。私はArc本体にも同じことをした。だが最優先したのは、言語ではなくアプリケーションをより短くすることだった。プログラムをとても短くしてくれそうな機能の中には、実のところ少数の初歩的なシーケンス・オペレーションを書くことにしか役立たないものがある。最も顕著な例はProlog流のパターンマッチングなのだが、『追加』や『削除』などにしか有効ではなかった。Prologはappendを書くためにはすばらしい言語だが、その以上のことになるとダメになる。

Arcを書いているときに私が目指した別の目標は、マッカーシーが始めた流儀をできるかぎり引き継ぐことだった。マッカーシーは1960年の原論文で、car, cdr, consといった公理から出発して、assoc, mapcarといった定理に至るようにLispを構築したと述べている。[1] 完全な言語までの最適な道のりがあるはずだ。それはどの道だろう? マッカーシーの論文はその点であまり成功しなかった。その後、Lispはマッカーシーのところにいた院生たちの手に移った。しかし彼らは当時、マッカーシーの公理的アプローチを続けることよりも、IBM 704で動くインタプリタの必要性のほうに気をもんでいた。それ以降ずっと、私たちは彼らのその場しのぎにつきあわされている。スティールとサスマンがSchemeに取り組り組み始めたのが、やり直そうとしたがほとんど唯一の例だったようだ。そしてスティールとサスマンは、少なくとも簡潔さ/力という観点からは、早くからいくつかの重大な間違いをした。

これは開拓する価値がある領域に思えた。下からは公理という力、上からは実際のアプリケーションにおける簡潔さという力を加えることにより最適なオペレータの核となるものをつくれたらと思った。実現したと言っているのではなく、目標だと言っているだけだ。すなわち、少ない公理から出発して、日常用途に関して完全なる言語に至る、最適な道を見つけるために。私は効率のために妥協した。チャーチ数は使ってない。[2] だが私は1960年の原論文の志をできるだけ保とうとした。

公理から言語を築くことが目的なのではない。そうすることで最高の表現力を得られるのではないかと思うから、そうしているだけだ。

Arcはどれくらいうまくやっているだろう? 他の言語よりどれくらい短くなるだろう? 測ってみよう。

挑戦として簡単な問題を示そう。普及している各言語の回答を集めて、長さを比較しよう。問題はこれだ。

(たとえばhttp://localhost:port/said のように)テキスト欄と送信ボタンを追加するページのURLを示すようなプログラムを作れ。送信ボタンを押すと、「ここをクリック」と書いてある1つのリンクのある2番目のページが示される。それをクリックすると3番目のページに行き「あなたは次のように書きました。○○○」と表示される。ここで○○○とは、ユーザが最初のテキスト欄に書いたものがそのまま表示される。3番目のページは、ユーザが実際に書いたものだけを表示すること。つまりテキスト欄に入れた値をurlで渡してはいけない。さもないとurlを編集して、最終ページの動作を変更できてしまう。

簡単だが、この種のテストはそうあるべきだ。そしてこれは不自然な例じゃない。ウェブ・アプリケーションはしょっちゅう、こういった処理をする必要がある。またArcしか持っていないような難しいライブラリに頼ってもいない。これはウェブ・アプリケーションを書くためのすべての言語が持っているべき内容だ。

Arcの回答は以下のとおり。
(defop said req
(aform [w/link (pr "you said: " (arg _ "foo"))
(pr "click here")]
(input "foo")
(submit)))

Arcに慣れていない人は、私の言葉を鵜呑みにせざるを得ないだろうが、これはコード化のトリックを使って圧縮したコードではない。 これは普通にArcで書くときの方法だと思う。

プログラムの長さに関する最も重要なテストは、行数や文字数ではなく、構文木のサイズだ。Arcでは23のノードの構文木がある。葉もしくはトークンが15と、8個の内部のノード。あなたの好みの言語ではいくつだろう?

もちろん標準ライブラリをインポートするコードは重要ではない。標準ライブラリは既にロードされていると仮定してよい。

この問題はArc Forumの http://arclanguage.org/item?id=722 にある。まだ載っていない言語での回答や、既存でももっと短い/正しい回答があるならば追加して欲しい。Arcに限らず言語を互いに比較するのも面白いだろう。


注釈

[1] 「記号表現の再帰関数とその機械による計算 Part ?」CACM, 1960年4月.
http://www-formal.stanford.edu/jmc/recursive/recursive.html

[2] 私はかつて整数nを長さnのリストとして表現したが、さんざんな結果に終わった。