2014年8月12日
JPL(ジェット推進研究所)におけるLispの顛末
本記事は、原著者の許諾のもとに翻訳・掲載しております。
この記事はジェット推進研究所(JPL)におけるLispの盛衰について、私の(しかもかなり偏った)個人的見地から書きました。JPLの所員としての立場で書いているのではなく、JPLの公的な立場を代弁するものでもないことをお断りしておきます(これについては読み進めていただければ分かります)。
1988-1991 ロボット工学の時代
私は1988年にJPLに入所し、自律移動ロボットの人工知能(AI)グループに配属されました。当時は今と違って政府の財源から資金が潤沢に流入していました。「AIの冬」が始まりかけていましたが、まだJPLには到達していませんでした。研究所の技術動向は最先端から数年遅れになる傾向があるようです。
当時のJPLはマーズ・ローバー・サンプル・リターン(MRSR)と呼ばれるマーズ・ローバー・ミッションの初期計画段階にありました。あの時代、宇宙ミッションはあらゆる意味で巨大でした。MRSRローバーは1トン近くの重さがあり、ミッションの予算は数千億円規模に達しようとしていました(その頃としては珍しいことではありませんでした)。
こうした状況下、私はデイヴィッド・ミラーという研究員の下で働いていました。彼は偶然にも私の論文の担当教官でもありました。デイヴィッドは、大きなローバーの代わりに小型ローバーを用いて惑星を探索するという、当時としては革新的なアイデアの持ち主でしたが、この考えは1988年にはなかなか受け入れられませんでした。小型ローバーが何か有効なことを成し得ると信じる人はごくわずかだったのです(今でも多くありません)。
うまく研究開発費を工面して、デイヴィッドはコリン・アングル(当時MITのロドニー・ブルックスの下で研究していた大学院生、現在はアイロボット社のCEO)を夏季インターンとして雇い入れました。コリンは 「トゥース」という名前の小型ロボット を制作しました。ちょうどMRSRミッションのたたき台として1トン近い重量の「ロビー」が制作されていたのですが、これとは見事に対照的でした。
当時、程度の差こそあれ、AI関連の開発はLispで行うのが常識でした。C++は存在感がなく、Perlは登場したばかり、Javaが登場するのは何年も先の話でした。宇宙船関連のプログラムはほぼアセンブラ、革新派ならAdaで書かれていました。
ロビーは2台のMotorola 68020プロセッサにそれぞれ(記憶が確かなら)8MBのRAMを搭載していました(当時の概念から言うと超大容量RAM。ロビーに対する批判の最たるものは、何をするにもメモリを食いすぎるということでした)。OSはvxWorksでした。一方トゥースは、それぞれ256バイトのRAMと2KBのEEPROMを搭載した2台のMotorola 68hc11で、8ビットのマイクロコントローラを積んでいました(後のロボットは桁外れの32KBのRAMを搭載した6811になりました)。
(時流の移り変わりは速く、劇的です。この前エンジニアが「128MBじゃ何もできない」と文句を言うのを聞きました)
ロビーとトゥースはLispでプログラムされており、ロビーは基盤上でLispを実行させていました。私たちが使用したLispは T3.1 です。ジム・ファービーの大きな助力によりSun-3からvxWorksに移植されたものです。ジムはエール大学からJPLに来て、他にもCommon Tという名前のTとCommon Lispの互換パッケージを制作しました。Common Tを用いると(Macintosh Common Lispとジムの書いたロビーシミュレータを用いて)Macintosh上でプログラム開発が可能になり、ロビー上でコードの変更なしで直接、結果コードを実行させることができました。
トゥースのプロセッサはLispを直接実行するには到底足りなかったので ^(1) 、代わりにLispで書かれたカスタム設計のコンパイラを使い6811のコードを生成しました。最初はロドニー・ブルックスのサブサンプション・コンパイラを使っていたのですが、後にサブサンプション構造による制約が嫌になったので、ALFA ^(2) という言語を自分で書きました。ALFAはその後すべてのシリーズのローバーをプログラムするのに用いられました。その中にはロッキーというシリーズも含まれていて、これはマーズ・パスファインダー・ミッションの 「ソジャーナー」 ローバーにやがて継承されました(ソジャーナーは1MBのバンク切り替え済みRAMを積んだIntel 8085を搭載しており、これはC言語でプログラムされていました。この経緯については後で述べます)。
トゥース、ロビーとロッキーシリーズは当時最も有能なロボットでした。ロビーはステレオビジョンのみをセンサーとして利用し、屋外環境で自律走行した初めてのロボットでした(注:その時のステレオビジョンのコードはラリー・マシーズがC言語で書きました)。当時、屋内でサンプル回収のタスクができるロボットはたった2台でしたが、トゥースはそのうちの1台でした。もう1台は「ハーバート」で、MITのロドニー・ブルックスの自律ロボットラボにいたジョナサン・コネルが、1~2年前に開発していました(でもトゥースはハーバートよりもはるかに信頼性が高かったです)。ロッキーシリーズのロボットたちは起伏の多い環境での操作に成功した初めての小型ローバーでした。1990年には、ロッキー IIIが完全に自律走行してサンプル回収をするというミッションの実演披露をしました。私が知っている限り、この機能は12年経った今でも再現できていません。
1988年から1991年の間はJPLで自律移動ロボットが大量に生産された期間でした。残念ながら、政治的には動乱の時期でもありました。悲しいことにデイヴィッド・ミラーのグループは、JPLで”正式に”ロボット工学研究が許された組織には所属していませんでした。結果、縄張り争いが熾烈になり、ロボット工学AIグループは解体、ほぼ全員のメンバーが去りました(ソジャーナーがC言語でプログラムされたのは、おそらくそのせいです)。
1992 – 1993 その他もろもろ
1993年には私のロボット工学の有終の美をかざるべく、アメリカ人工知能学会の移動ロボットコンテストに出場しました。私のロボット(「アルフレッド」という名前のRWI B12)は3部門のうち2部門にエントリーし(もう1つの部門はアルフレッドにはない遠隔操縦機を備えているのが条件でした)、優勝と準優勝を獲得しました(1つの部門ではアルフレッドが完走できた唯一のロボットでした)。何がすごかったと言えば、コンテストに関するコードを3日間で書き上げたということです(会議のため搭乗した飛行機の中で書き始めました)。ほとんどのチームがC言語を使っていたのにもかかわらず、私はLispでプログラムを書いていたことが成功に貢献したと思います。
1993年にはガリレオの磁気探知器のパッチコードを生成するのにMCLを使いました。磁気探知器はそれぞれ2KBのRAMとROMを備えたRCA1802プロセッサを搭載しており、お役御免になって長いApple IIで稼働する開発システム上で、Forthを用いてプログラミングされました。この機器はコードの途中でメモリ不良を起こしてしまっていました。該当の不良箇所を使わないようにコードにパッチを当てる必要がありました。磁気探知器チームは当初、開発環境を復活させてコードパッチを生成するのには時間がかかりすぎるとして、手を着けていませんでした。私はLispを用いて、その機器(ハードウェアのシミュレータを含む)のためのForth開発環境をゼロから書き、その環境上でパッチを生成しました。片手間でやってもこのプロジェクト全体には3カ月ほどしかかかりませんでした。
1994~1999 – リモート・エージェント
1994年にJPLはリモート・エージェント(RA)、つまり宇宙船自律制御システムに着手しました。C++に移行するようにという執拗な政治的圧力があったにもかかわらず、RAは全てCommon Lispで書かれました。一時はシステムの一部(プラン部分)をC++に移植する試みが行われましたが、1年後に頓挫しています。この経験から、Lispを用いていなければリモート・エージェント計画は失敗していたと言っても過言ではないと思います。
リモート・エージェントプロジェクトの過程では、4種類のCommon Lispを用いました。MCL、Allegro、HarlequinとCLISPです。これらを3つの異なるOS、すなわちMac OS、Sun OSとvxWorksを組み合わせた環境上で稼働させていました。Harlequinは後に宇宙探査機に乗って宇宙に行ったLispになりました。地上での開発はMCLとAllegroで行われました。(CLISPもvxWorksに移植されていたので、もしスレッドが欠けるという問題がなければ、フライトLispとなっていたでしょう)。異なるOS上で私たちは苦もなくこれらのコードを行き来させていました。
リモート・エージェントのソフトウェアはHarlequin Common Lispをカスタム移植したものの上で稼働し、NASAの新千年紀プログラム最初のミッション、 ディープ・スペース1号(DS1) に搭載されて宇宙に行きました。1999年5月の2日間、リモート・エージェントはDS1を制御し、その期間中、地上のテストでは起こらなかった乱調状態をデバッグして、修正もできました。(100億円超のハードウェアで稼働するプログラムを、1億6000万キロ離れた場所からデバッグするのは面白い経験でした。REPLを宇宙探査機上で稼働させてみると、問題の発見と修正に非常に役立ちました。 リモート・エージェントのバグの話 はそれ自体、1つの面白い読み物です)。
後にリモート・エージェントは「NASA のソフトウェア・オブ・ザ・イヤー」と称えられました。
警告。 ここから話の展開がネガティブになってきます。不快な話、シニカルな暴言や妄言を聞く気がなければ、ここで読むのをやめましょう。警告しましたよ。
1999 – ミッション・データ・システム
さてこのように次々と成功を修め、輝かしい業績をあげたLispを、さぞかしNASAは受け入れ尊重したと思うでしょう。もちろんそれは間違いです。
新ミレニアム計画は、NASAの新しい「より良く、早く、安く」という哲学のフラッグシップとなるはずでした。言い換えるとそれは、私たちに割かれた予算は信じられないほど少なく、スケジュールは不可能なほど厳しいということを意味していました。
必然的に日程と予算の超過が生じた結果、プロジェクトにはスケープゴートが必要でした。決定的な転換点となったのは、JPLのトップマネージャーを多数含む約200人が出席した大規模な検討会です。ソフトウェア統合担当のエンジニアがプレゼンテーションで、うまくいっていない全ての事柄をリストアップしている時でした。私の知らない誰かがそのエンジニアの話を中断し、この状況を改善するために何か1つだけ変えるとすれば、それは何だと思うか問いかけました。それに対する彼の答えは、Lispの排除でした ^(3) 。
この出来事によって、JPLにおけるLispの使用はほぼ打ち切りになりました。リモート・エージェントは主流のフライトソフトウェアからフライト試験(今ではRAXに改名)に降格されました。リモート・エージェントはまだ飛行していましたが、探査機を2日間制御しただけでした。
私は次のプロジェクト(JPLミッション・データ・システム、またはMDS)でLispの復活を目指しましたが、後の祭りでした。Lispに対する主な反発の1つに対処しようと試みましたが、非常に大掛かりだったため、ゲーリー・バイヤーズを雇いました。彼はMacintosh Common Lisp(MCL)のコンパイラを記述してMCLをvxWorksに移植した人物です(彼は途中でLinuxとSolaris向けのポートも作成しました)。Harlequinのイメージが16MB程度なのに比べ、MCLの場合はわずか2MBでしたが、それは問題にされませんでした。Lispは廃れてしまったのです。少なくともJPLではそうでした。2年後、ゲーリーは彼の功績が誰からも利用されないことを悟り、JPLを去りました。その数カ月後、私もJPLを辞めてGoogleに入社しました(Linux向けのポートにおけるゲーリーの功績は、結果的にOpenMCLにつながったため、全く無駄になったわけではありません)。
JPLで行われた主なLisp開発は少なくともあと2つあります。マーク・ジェームズは、探査機ボイジャーのハードウェアの問題を診断するSHARP(Spacecraft Health Automated Reasoning Prototype)というシステムを作りました。クルト・エッゲマイアーが記述したPlan-Itというプランニングソフトウェアは、いくつかのミッションの地上計画に使用されました。他にもまだたくさんの事例がありますが、全て忘れられて久しいです。
2000~2001 – Google
このセクションは、JPLにおけるLispの歴史を語る本題からは少し離れますが、私がGoogleで経験したことのいくらかは興味深いと思います。
私がJPLに12年間も勤務したのは、ソフトウェア業界のあり方に衝撃を受けたからです。経営サイドが目指してきたソフトウェア工学の開発プロセスは、人材を交換可能なコンポーネントのようにそのプロセスに当てはめることでした。これらの”コンポーネント”の”インターフェース仕様”には、通常、エンジニアが”訓練”で習得したツールのリストが含まれます(私はプロフェッショナルな活動において”訓練”という言葉を使うことを嫌悪しています。訓練とは犬のしつけです。人間は教育すべきであり、訓練すべきではありません。両者には非常に大きな違いがあります)。
私の考えでは、ソフトウェアエンジニアを交換可能なコンポーネントと見なすモデルの象徴はJavaです。詳細にはあまり触れずに、これだけ言っておきます。私がLispでプログラミングした経験から言うと、Javaの欠点は火を見るより明らかで、Javaでのプログラミングは延々と続く苦しみの人生を意味します。ですから、私はJavaのプログラマにはなるまいと誓い、そのために90年代後半のソフトウェアエンジニアの仕事の90%から閉めだされてしまいました。しかし、私はそれでも構いませんでした。なぜなら、研究者としてそれなりに成功を収めようと努力していたからです。とはいえ、リモート・エージェント以来、私はますます不満を募らせていました。そして、私の不満が頂点に達した頃、Googleで働く機会が与えられたのです。
私がGoogleで働くことを決めた理由の1つは、Javaが使われていなかったからです。皆さんのご想像通り、私に課せられた最初の仕事は、GoogleでJava開発の立ち上げを指導することで、それが後に Google AdWords に発展しました。ありがたいことに、私にはJavaの知識を持つ部下のエンジニアがおり、彼はJavaを使うことにさほど抵抗がありませんでした。昔の上司と部下の関係では、部下が全ての業務を担いますが、手柄は上司のものです(しかし実際には、私も請求システムのコードを記述して、不誠実な従業員からもクレジットカードの番号を保護できる優れたセキュリティシステムを構築しました)。とはいえ、AdWordsバージョン1の大部分を記述したのは、部下のジェレミーです。
私はGoogleでもLispを導入しようとしました。JPLでLispを売り込んだ経験を生かし、私は準備を整え、広告チームの全てのメンバーに立派なデモを披露したところ、皆がいいアイデアだと納得しました。残るはエンジニアリング担当の副社長の承認を得るだけというところまでこぎつけたのです。その時の会話は以下のようなものでした。
私:「お話したいことがあるのですが…」
副社長:「君が言いたいことを当ててみよう。Smalltalkを使いたいんだろう?」
私:「いえ、違います…」
副社長:「Lispか?」
私:「そうです」
副社長:「冗談はよせ」
GoogleでのLispの話はそれで終わってしまいました。今振り返ってみると、あの時彼が間違った決断をしたとは思いません。ソフトウェアエンジニアを交換可能なコンポーネントと見なすモデルは、Googleでそれなりにうまく機能していたようだったからです。ただそのビジネスモデルは、私が関わりたいものではなく、特にコンポーネントを供給する側としては気乗りしませんでした。その結果、私は1年でGoogleを辞め、JPLに復帰したのです。
2001~2004 - あなたの税金は有効活用されているか?
JPLに戻った私に与えられた仕事は、(驚いたことに)検索エンジンでした。私は実際には検索エンジンの仕事を一切していなかったのですが、Googleに1年いたことで、検索エンジンのエキスパートになったと判断されたようです。私にとっては幸運なことに、JPLでの検索エンジンの仕事は、Googleにおけるそれとは意味が異なりました。Googleでの検索エンジンの仕事は、実際に検索エンジンを開発することでしたが、JPLの場合は、検索エンジンを買うことで、その分野では私は経験豊富でした(要はGoogleに電話して発注する仕事です)。私がJPLの官僚的な人々を介した発注の手伝いをすることに、どれだけの税金が支払われたかは、皆さんに知らせない方がよいでしょう。
閑話休題。
解説
JPLでLispが廃止されたことは悲劇です。LispはJPLでしばしば行われるソフトウェアの開発に適した言語です。つまり、ユニーク、かつ、高度にダイナミックなアプリケーションで、非常に厳しい予算と日程での開発が求められるケースです。このような環境におけるLispの有効性は、類まれな技術的功績の長期にわたる記録によって、十分証明されています。
この状況が特に皮肉なのは、C++(今ではJava)を選択してLispを捨てる理由として進められてきた議論が、JPLは”業界最良の事例”を使うべきだという根拠に基づいているからです。この議論の問題は2つあります。第一には最良の事例が標準的な事例と混同されていることです。両者は同じではありません。そして第二に、最良の事例(もしくは標準的な事例でさえも)は、タスクによって左右されるものではないと考えられていることです。つまり、ワープロのコードを記述するために最良の方法は、宇宙探査機の制御システムのコードを記述する上でも最良の方法だという憶測です。しかし、そうではありません。
このような事態を目にするのは、非常に悔しいことです。現在の私の仕事はソフトウェアの確認および検証で、C言語やC++のようなセマンティックがうまく定義されない純粋な命令型言語に直接端を発する問題を解決しています(Javaでは状況は多少ましですが、大差はありません)。しかし、当然のごとく、Lispのようにセマンティックがきちんと定義される非命令型言語を使用するという選択肢はありません。私がLispという言葉を言いでもすれば、私の評判はLispで全てが解決できると思っている愚か者ということになるでしょう。ですから、私は(ほとんどの場合)口をつぐんで、大量の税金が無駄使いされるのをなすすべもなく見ています(このあからさまな無駄使いに対して、民衆の怒りの波が救いの手を差し伸べることを期待したいですが、政府事業で定期的に生じる甚だしい浪費の規模を考えると、それはほんの小さな希望に過ぎません)。
エルトン・ジョンの言葉を借りれば、これは「悲しい、とても悲しい。悲惨な状況だ」ということになります。現時点での私の最大の希望は、「AIの冬」にLispに起こったのと同じことが、ドットコム企業の破綻によってJavaにもたらされ、ついには”ドットコムの冬”から抜けだして健全な世界に移ることです。しかし、その見込みは薄いと思っています。
注釈:
追記:多言語の統合に関する悩みの種の多くは、LispとC言語の通信を可能にするプロセス間通信(IPC)システムが原因でした。IPCはC言語で記述されたセントラルサーバに依存しており、度々クラッシュしました。Lispを排除することでこれらの問題が実際に軽減されたのは、信頼性の低いIPCが不要になったからです。結局のところ、JPLにおけるLispの廃止は、C言語の信頼性の欠如によってもたらされたという側面が少なくなかったことは、この上もない皮肉です。
-
Lispは相当に処理能力の低いプロセッサ上でも稼働します。私が最初に触ったLispはP-Lisp で、48KBのRAMを搭載したApple IIで稼働していました。ディスク3枚までの「ハノイの塔」問題が能力の限界あたりでした。 ↩
-
ALFAとはA Language For Action(アクションのための言語)の頭文字をとったものです。私の計画は、いつかBETAと呼ばれる言語を設計することでした。Better Even Than ALFA(ALFAよりも更に良い)という意味です。しかしBETAに着手する時間の余裕はありませんでした。 ↩
-
ここで、なぜ彼はそう言ったのかという疑問が残ります。当時なぜ彼がそう言ったかというと、彼はほとんどの時間を多言語の統合に関する問題の対応に費やしていたからです。しかしながらこれは、次の事実によって覆すことができます。検討会の少し前、私はその統合担当のエンジニアに会い、彼が遭遇しているLisp関連の問題のことなら何でも手伝いたいと申し出ました。その時彼は、助けてもらうことは何もないと返答したのです。ですから、LispをC言語と相互運用しなければならなかったことで生じた問題があったのに、その問題を解決するための誠実な取り組みが成されたとは思えません。 ↩
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
- Twitter: @yosuke_furukawa
- Github: yosuke-furukawa