Lisp:よくある誤解

Lisp:よくある誤解

Lispについてのよくある誤解と、その中にあるちょっとした真実

はてなの質問:

プログラミング言語で最強(スケーラブル)なのは、 Lispだと思われます。 http://jp.franz.com/index.html

しかし、 世間ではマイナー言語のようです。 なぜでしょうか。

についた回答のいくつかには、「Lispを少しだけかじった人がしがちな誤解」が 含まれてるようなので、それをネタに少し解説してみます。

ただ、誤解が生じるのは、やっぱりそれなりの理由があって、従ってその 誤解の中にも(条件つきの)真実が含まれていることがあります。 そのへんまでをも含めて考えてみましょう。以降、引用は回答からです。

Lispはスクリプト言語?

一昔前まで、これらのスクリプト系の言語は「とてつもなく遅い」のが嫌われる最大の要因でしたが、最近のコンピューターの性能向上でようやくRuby,Python,Lispといった言語が実用的な速度で動くようになりました

事実

最近、スクリプト系のScheme処理系が流行っているのが、こういう誤解の元かも しれません。

歴史的に見ると、LispもSchemeも一番最初の処理系こそインタプリタでしたが、 非常に早い段階からネイティブコンパイラが開発されています。 一時期は最適化コンパイラの研究でも先頭を切っていたんじゃないかと思います。

最近のコンピュータの性能向上で、「ネイティブコンパイルしないLisp処理系」でも 実用的になった、というだけでして、現在安定している処理系を眺めれば未だに ネイティブコンパイルするものの方が多いくらいじゃないでしょうか。

1980年代後半あたりで、「実用的な速度で」CG制作が出来た唯一の環境は Lispマシンでした (「速度の必要な部分はCで書いて…」なんて話じゃないですよ、 ソフトは全てLispで書かれて、ネイティブコンパイルされていました)。

真実

まあ、そうは言ってもLispマシンが(当時の他のハードウェアに比べて)速かったのは ハードウェアによるサポート (タグを見ての分岐とか、GC用の特殊ビットとか) が あったせいもあると思います。現在のハードウェアはどっちかというと 「CやFortran向け」でして、動的言語はかつてLispマシンがハードで持っていた ような機能をソフトウェアでエミュレートしてると言えるかもしれません。

Lispは高速なプログラムが書けない?

また高速なプログラムが書けるかと言う問題もあると思います。
(Cの方が機械語に近い言語なので高速なプログラムを書きやすいと言う意味)

事実

Cの方が機械語に近いのは事実ですが、LispでもほぼC並に速いコードを 書くことは可能です。Lispマシンではなく、現代のアーキテクチャでも。

Common Lispの規格の中には最適化オプションの規定もあって、 speedというパラメータを3(最大)にすると、Cで言う-O3みたいな 最適化をやってくれるんですが、さらにsafetyというパラメータを0にして、 型宣言をつけてやれば、多くの処理系は実行時型チェックを省きます。 最適化オプションの指定は コンパイル単位毎だけでなく関数毎にも出来るので、ボトルネックの 関数だけをそのようにコンパイルすることが言語仕様内で可能になっています。 この状態で生成されるコードは、Cで同じロジックを書いてコンパイルした コードにほぼ遜色ありません。

また、Common Lispの規格の中にはdisassembleという関数も含まれています。 Cでもディスアセンブラは言語仕様外でしょう。当然、使うから含まれているわけで、 Common Lisperは最適化の最終段階ではボトルネックの関数を ディスアセンブルして生成される機械語を見ながらチューンしてゆくこともあります。

Schemeになりますが、Stalinという処理系はグローバルプログラム変換と 型推論によってこれも多くの実行時型チェックを省いたコードを生成します。 作者は本人の研究で多用する数値計算を行うためにこの処理系を開発しており、 「Cより速い」と言っています。

真実

普通に(教科書的に)書かれたLispコードは、コンパイルしても確かにCより 数倍遅いでしょう (ソースコード量は数分の一でしょうが)。

C並に速いLispコードを書くためには、いくつも気を付けなければならない ことがあります。

なので、C並に速いLispコードは見た目も安全性もC並になる、というのが 私 (Shiro) の経験です。

もっとも、Lispの場合、大量の型宣言はマクロで隠せるのでCよりずいぶん楽です。 また、別のところでも書きましたが、最適化の途中段階ではいくつものアイディアを 実装してベンチマークを取ることが重要ですが、マクロを利用することでアルゴリズムの 一部をパラメタライズしたバージョンを簡単に作れるので、より多くのアイディアを 試しやすい=結果としてより速いコードに到達できる、ということは言えます。

(上で「ほぼ」C並、と書いた理由にちょっと触れておきます。配列を順番に 触ってゆくコードは、Cでコンパイルしたなら、普通は現在の要素のアドレスが レジスタに入ってレジスタ間接でアクセスして、そのレジスタをインクリメントする、 みたいな感じになるでしょう。Allegro CLのver 7では、配列の頭のアドレスが ベースレジスタに入って、もう一本のレジスタにインデックスが入り、 インデックス付きレジスタ間接になります。これは、ループ中にGCが起きると 配列が移動される可能性があるためです。それだけレジスタを圧迫するので、 特に複数の配列をinner loopで触ってるとちょっともどかしいですね。 GCを工夫して、配列の途中を指しているポインタも移動に応じて変えられるように できればいいんでしょうが、今度はGCの負担が大きくなりそうだしなあ。)

Lispプログラマの確保が大変?

表記法が一般的でなく、習得が難しい。必要なスタッフの確保ができない

事実

Paul Grahamが言っています。 「10人のLispハッカーを集められないなら、 たぶんあなたの会社はソフトウェアを開発するのに適さない都市にいるんだ」と。

実際、USでは「コンサルタント」を名乗るフリーのLisp屋というのは、 いるところにはいます。絶対数は少ないですが。彼(女)らはLispの プロジェクトに飢えているので、Lispスタッフ募集をかければ わらわらと寄って来るでしょう。

日本だとあんまり開発を行うコンサルってのが一般的で無い印象が あるので、フリーのLisp屋というのは生きにくいかもしれません。

真実

そうは言っても、企業で、自分の周囲を見回してLispプログラマが わらわら居るって環境はあまり普通じゃないでしょうねぇ。

前の会社でLispを使った時は、直属の上司とその上のVice Presidentが 筋金入りのLispプログラマでした。そのおかげでAllegro Common Lispを すんなり買ってもらえたわけですが、なかなかそういう環境って無いと 思います。Lisperが多いと思われるCG業界でも、その職場に他にLispメインの プログラマが居なかったことを考えると、他の業界ではさらに Lispプログラマの密度は低いと想像されます。

ただ、Lispの場合、何十人もの部隊を率いるってスタイルにあまり 馴染みがないですね。2〜3人のLisperが居ればかなりのことが出来るんで、 職場で「自分以外にもう一人」のLisperを見つけることがクリティカルマス突破の 重要な鍵かもしれません。

Lispには安定して世界標準な言語環境がない?

以下は私の推測ですが、Lispが流行らない原因は、 「安定していて世界標準的な言語環境がない」のが原因ではないかと思います。(つまり、今作ったLispのプログラムが、3年後に安定して動く環境があるかどうか確信できないので作る気にならない。

事実

これは事情を知る人なら椅子から転げ落ちそうな意見です。Common LispがANSIという 世界標準になったのが1994年でしたっけ。商用を含むいくつかの処理系は 十分枯れて安定してます。ANSIの範囲内で書いたプログラムは10年前のものでも 確実に動きますし、10年後にもほぼ確実に動くでしょう。

Schemeは数年に1度の規格改定で非互換な変更を持ち込む場合があります。 ただ、メジャーな処理系は後方互換なモードを用意すると思われます。

正式な言語仕様の無い、実装=仕様みたいな言語と混同するのは勘弁して欲しいです

真実

…が、実は公式な仕様範囲「だけ」ではなかなか実用アプリが書けないのも事実でして。

あれだけ仕様の分厚いCommon Lispであっても、実際にアプリを書く際には どうしても処理系依存の拡張を使います。ましてやSchemeの場合、言語仕様のみで 出来ることはプログラム演習の宿題くらいのものなので、処理系依存の拡張は 使いまくりにならざるを得ません。SRFIでだいぶましになりましたが、OSとの インタフェースやI/O、ネットワーキング、非同期処理などはまだまだです。 これら処理系の拡張は、実装者が気分を変えたり、処理系そのものがディスコン されると当然使えなくなります。 (Common Lispの場合、色んな処理系で使えるような拡張ライブラリがオープンで 出ていたり、他の言語で書かれたライブラリを呼び出すAPIが UFFIとして統一されていたりするので、気をつけていれば 処理系の乗り換えは難しくありませんが)

もっとも、言語仕様「だけ」見ればCだってそう変わらないと思うんですが、 あっちにはPOSIXもありますしねぇ。やっぱりOSのAPIを握った言語は 強いですなぁ。

Lispは大学以外では使われていない?

20年以上コンピュータ業界にいましたが、大学などを除いて一般的に使われているのを見たことがありません。

事実

Franz社の事例サイトとか 見ると大学以外でも結構使われているようですよ。

Lisp/Schemeアプリの主流は特定の業務向けのカスタマイズされたシステムで、 インハウスで開発され使われることも多いので、あまり表に出て来にくいという 事情もあります。

Joel Spolskyもどこかで書いていましたが、コンピュータ業界と一口に言っても 均質ではなく、使われる用語やツールから常識までも異なる様々な業界に 分断されています。一つの業界で長く過ごしても、別の業界で使われている 言語が何かを全く知らないということは珍しくありません。 なので、業界何年、という言葉をそのまま取るのは危険です。

真実

いや、Recent Storiesに何年も前の 事例が載ってるのはやっぱりどうかと思います… Naughty Dogも確かLisp やめちゃったし、Izwareもこの先心細いしなあ。

というわけでLisperのみなさんがんばって事例を増やしましょう。

LispはGUIには向いていない?

事実

1980年代前半から、ビットマップなGUIがありました (WikiPediaにスクリーンショットあり)。 もちろん全てLispでかかれています。CLiki:Lisp Machine Videos

このGUI、ただのグラフィカルな表示ではありません。表示されたもの全てが Lispオブジェクトであり、マウスオーバーすればそのオブジェクトのメソッドを 呼び出すことができます。例えばプログラムの実行結果が、コンソールに 整数の1を出力したとします。それは単なるテキストの"1"ではなくて、 整数の属性を保持しているので、マウスを重ねてinspectすれば整数クラスに 定義されたメニューが出てきます。Lispオブジェクトのリストをprintすれば、 各要素がそれぞれの属性を保持していてそれに依存したメニューが出るし、 括弧にマウスを持ってけばリストとしてのメニューが出る、といった具合です。

これを発展させて規格としたのがCLIM (Common Lisp Interface Manager)で、 全てCLOSの上に組んであり、各オブジェクトが、どういうデバイスの場合にどのように表示され、 どのようにユーザ入力を受け付けるか、ということを全てメソッド定義で カスタマイズできます。

真実

CLIMはめちゃめちゃ強力なんだけれど、それだけで独自世界を作っちゃってるんで、 多くのプログラマが使い慣れたGUIツールキットが使えないんですなあ。 GUIってAPIが膨大だから、プログラマもなかなか切り替えたがらないしねえ。

議論、コメント

Shiro: yoriyukiさんのLispが何故使われないかがなかなかツボを突いていたのでこんなのを書きました→Lisp:よくある正解

More ...