2002年5月1日 by エリック S.レイモンド

ビグルス枢機卿はこの告白を引き出すのに異教徒エリックを4時間以上も安楽椅子に拘束した...

初めて Python を見たのは偶然からです。その時見たものは全く気に入らなかったです。たしかそれは1997年初期の出来事です。最近、Mark Lutz(マーク・ルッツ)の本、 Programming Python (日本語版: Pythonプログラミング )がオライリー社から出版されました。オライリー社の新作から選ばれた本は時々私の玄関口に届きます。 それは私が理解するのをあきらめたことに気付いた組織内部の謎の恩人によって届けられます。

その中の一つがProgramming Pythonでした。私はコンピュータ言語を集めているのでこれにはいくらか興味を引きました。 私は2ダース以上の汎用言語を知っているのでコンパイラとインタプリタを冗談半分で書き、そして多くの専用言語とマークアップ形式の言語をデザインしました。(これを書いている時点で)最近完成したプロジェクトは PNG(ポータブル・ネットワーク・グラフィックス)画像を操るための SNG と呼ばれる専用言語です。関心がある読者は SNG のホームページ http://www.catb.org/~esr/sng/ にサーフィンできます。また、私のレトロ・コンピューティグ博物館のページ http://www.catb.org/retro/ では奇妙な汎用言語のインプリメンテーション(実装)をいくつか書きました。

Python については他のプログラムから呼び出され共働するために、自身に内蔵されたメモリ管理とすばらしい機能をもったインタプリタ型の言語であることを聞いていました。これは今日では「スクリプト言語」と呼ばれています。ですから私は心に最高の一つの疑問を携えProgramming Pythonに没頭しました。Python に出来て Perl に出来ないことは何か?

Perl はもちろん現代のもっもビッグなスクリプト言語です。活動的な Perl コミュニティーによって構築された一部のモジュールの巨大なコレクションと、部分的な Unix ライブラリとシステム・コールの包括的なセットのおかげで、システム管理者のスクリプト言語として大いにシェルに取って代わりました。言語は一般的にネット上の「ライブ」なコンテンツの約85%を支える CGI 言語であると推定されます。(Perl創造者の)Larry Wall(ラリー・ウォール)は正当にオープンソース・コミュニティーの重要なリーダーの1人であると見なされています。そしてしばしば現在の神格的なハッカー、リーナス・トーバルズとリチャード・ストールマンに隠れ第3番目の神として位置づけられます。

ちょうどその頃、多くの小さなプロジェクトのために Perl を使っていました。Perl は構文といくつかの局面がアドホック(その場しのぎ)で、注意して使わなければイライラする傾向があるとしてもまったくパワフルな言語だと分かっていました。Python は他のスクリプト言語と同程度の段階にあると読んだので、私は第一に Perl との明確な差異を探しました。

私はすぐに、誰もが注目する奇妙な特徴につまずきました:それは空白(インデント=字下げ)がこの言語の構文にとって重要だという事です。そして C と Perlの大括弧を用いた構文に類似する物がありません; 代わりにインデントの変化がステートメント・グループ(記述)の境界を設定します。この事実に出くわしたほとんどのハッカーのように、再帰的な嫌気にひる んでしまいました。

1970年代のように数ヶ月をかけて FORTRAN でバッチ処理をプログラミングするほど私は年寄りではありません。近頃のハッカーはそうではありませんが、私たちの文化は特定の言語だけを用いる古いスタイルのありさまがどれほど不快であった事か、なんとかして記憶にとどめているように思います。まぁ当時、 Pascal と C においてトークン指向の新しいスタイルの構文について説明するのに使用された「フリー・フォーマット」という用語はもう少しで忘れられるところでした; この数十年間すべての言語がそのように設計されています(まったくいい加減だけど)。誰もが不意に恐竜の糞の大量の山に踏み入れたような反応でこの Python の特徴をひどく非難することでしょう。

確かに間違いなく私もそのように感じました。そして残りの説明をあまり関心を持たずにざっと読みました。ボタンやメニューを構築するベーシックな GUI の機能が Perl よりもすっきりした構文でしたがその他に Python を推薦する要素はほとんど見あたらなかったです。

本を棚に戻して、この言語について理解したことを確認するためには GUI 中心のある種の小さなプロジェクトをコード化してみることだと考えました。しかし Perl と有効に競い合うようなことは信じてもいなかったのです。

その構想は何ヶ月ものあいだ他の出来事に抑えつけられていました。1997年の残りの期間はとても忙しかったです;この年は「伽藍とバザール」のオリジナル・バージョンを公開しました。しかし何とかして、かなりの規模で複雑さを含む2つの Perl プログラムを書きました。そのうちの keeper は Metalab ソフトウェア・アーカイブでファイルを管理するアシスタントとして働いています。その様子は http://metalab.unc.edu/pub/Linux/!INDEX.html で見ることが出来ます。もう片方の anthologize は Linux ドキュメンテーション・プロジェクトの HOWTOs を Linux 第6版のためのポストスクリプトを自動的に作成するのに使われました。どちらのプログラムも Metalab で入手可能です。

これらのプログラムを書いたことで Perl にはさらに不満を持ちました。大きなプロジェクトは Perl への不満を増大するように思いました。100行で風変わりに思える書式が、1,000の刺をもってしても通り抜けられない生け垣に見えてきました。それはちょっとした風味と表情の豊かさに見えますが、大きなコードを見据えて一貫したスタイルを維持するのに苦労します。大きなプログラムをコントロールしようと追加/改善された機能(オブジェクト, レキシカル・スコーピング, use strict など)は脆く、貧弱な感がありました。

Perl の大きなコードはほんの数日でも目を通さなければこれらの問題が結びついて読むことをさらに難しくさせます。また、私はアプリケーションの問題よりもこの言語と格闘する時間に多くを費やしていることに気付きました。そして、すべてのうちで最も罪を免れないことは醜いコードを生み出すということです--これは大問題です。醜いプログラムは危険な吊り橋のようです:これらはきれいな物より崩壊しやすいです。なぜなら人間(特に技術屋)が美を知覚する方法と、我々が複雑さを処理して理解する能力は親密な関係にあるからです。エレガントなコードを書くことがやっかいな言語は、良いコードを書くことをも困難にします。

私が携えている2ダースの言語の基準となっているサインはその言語の設計であると発見しました。1997年の中頃、"よりよい方法がなければならない"と思って、より上品なスクリプト言語をあちこちに捜し始めました。

デフォルト言語として C に戻ることは考慮しませんでした。新しいプログラムにおいて自分自身でメモリを管理することに意味をなす時代は終わっていました。--例外としてカーネルハッキングや科学技術計算、3Dグラフィックスのような専門領域ではハードウェアを最大限活かすためにメモリの使用により最高速度と厳しいコントロールが絶対的に要求されます。

バッファ・オーバーラン、ポインタ-エイリアスの問題、 malloc/free によるメモリ・リークなど、その他関連する全ての問題を今日のマシン上でデバッグするオーバーヘッド(負荷)には気が狂いそうです。スクリプト言語のメモリ管理のオーバーヘッド(無駄)に対して少数のサイクルと数キロバイトのメモリを交換して、人間の貴重な時間を節約する方が賢明です。まぁこの戦略が1990年代半ば以来、 Perl の爆発的な成長を促したのです。

今度は Tcl に手を出して見ましたが Perl よりもさらに貧弱であることを発見しました。私は古くからのリスパー(LISPer)です。同様に LISP と Scheme の現在の方言も探ってみました--しかし LISP の歴史は相変わらずで、設計は良くてもドキュメントが無かったり、POSIX/UNIXの機能へのアクセスが不完全なのです。それらは些細なことなのです が、深く断片化したユーザーコミュニティーによってほとんど役立たずにされていました。Perl の人気は偶然ではありません;競争相手のほとんはプロジェクトが大きすぎて Perl よりなお悪いか、理論上は優れているけれども役に立つものであるとは言い難いものなのです。

つぎに Python を見たのは初めての時と同じように偶然からでした。1997年の10月、fetchmail-friends メーリングリストの一連の質問において fetchmail の設定ファイルに関する問題が増大していることをエンド・ユーザー達が明らかにしてくれました。この設定ファイルは古典的な UNIX のフリー・フォーマットのシンプルな書式ですが、複数のサイトに POP と IMAP のアカウントを持っているとぞっとするぐらい複雑になってしまいます。例として私が書いたシンプルな Listing 1 を見てください。

Listing 1

そこでエンド・ユーザーに分かり易い設定エディタ、 fetchmailconf を書いて問題の対処にあたりました。fetchmailconf の設計目標は明確でした:ファイルの書式を、選択ボタン、スライドバー、記入フォームを用いて人間工学的に正しい GUI インターフェースに置き換えて完全に隠してコントロールすることです。

これを実現するのに Perl では私の興味をひかなかったです。Perl の GUI コードを見てみると、Perl と Tcl が釘だらけ混合物に見えて、私のピュアな Perl のコードよりさらに醜いようでした。ここで私が6ヶ月以上前に計画したことを覚えていたのがポイントです。そうです。Python で実地経験の機会を得たことだったのです。

もちろん、初心者には取っつきにくい Python のインデントの重要性に再び直面しました。しかしこの時、自ら進んでラフな GUI 要素の一握りのサンプルを描いたのです。実に奇妙なことに20分後には Python のインデントの使用が不自然に感じなくなりました。普段やっている C プログラムのインデントのように、コードを単にインデントしてやるとそれはうまくいったのです。

これが第一の驚きです。次に、2,3時間プロジェクトのために作業してみました。すると、(Programming Pythonで新しい特徴を探すために手を休めましたが)普段タイプするのと同じくらい速くコードを生成できるのです。これを悟ったときには本当にビックリしました。コーディングしてみることはとても重要な努力です。タイプするものはあなたが思ったことを言葉にするようにはうまくいかないでしょうが、問題の考えと一致しなくても立ち返り繰り返すのです。そして、すぐれた言語設計を知る手段として、言語の経験を得ると同時にこの種の失敗の割合が急速に減少するかを測ってみることなのです。

一般的に、タイプするのと同じように速くコードを書くことが出来てそして失敗率がほぼゼロに近づいたならばそれは言語への熟成を達成したことを意味します。しかし私はそれにはうなずきませんでした。なぜなら、言語とライブラリの特色を検討するのをすっかり中断していたからです!

この事が、私が例外的な素晴らしいデザインを扱っているという Python への最初の手掛かりとなりました。ほとんどの言語は先に挙げた失敗率が下がるよりも前に沢山の関数のセットを覚えなければならない摩擦と不器用さを組み込んでいます。Python は私が今まで使った汎用言語のうちでこのプロセスを逆にした初めての言語でした。

しかし、私が関数のセットを学ぶのに多くの時間を費やしたという意味ではありません。私は6日の作業を経て GUI を持った fetchmailconf を書き上げました。そのうちの2日間ぐらいは Python そのものを学ぶために費やしたと思います。この事は他の特性を反映しているのです:コンパクトなのです--あなたは頭の中で関数のセット(と少なくともライブラリの概念の索引)を記憶しておけるのです。C は素晴らしくコンパクトな言語です。Perl は悪評高くはないでしょう; Perl には簡潔さを「実現するひとつ以上の道がある!」けれども可能性にとどまっています。

しかしまだ発見の劇的な瞬間が待ち受けていました。私のデザインに問題がありました:ユーザーの GUI アクションから簡単に設定ファイルを作成することが出来ましたが、編集するのがとても難しかったのです。言い換えれば、編集可能なようにフォームへ読み込むことが問題だったのです。

fetchmail の設定ファイルの書式を解析するプログラムはかなり手の込んだものでした。実際には YACC と Lex で書きました。この2つの古典的な UNIX ツールは C で言語を解析するコードを生成します。fetchmailconf が既存の設定ファイルを編集するにはその手の込んだ解析プログラムを Python で複製する必要があると思いました。しかしこれには気がすすまなかったのです。その理由のひとつは作業の複雑さ、もうひとつは2つの異なった言語の解析プログラムが同じように動作するか確証がなかったからです。そして最後に、私が書いた解析プログラムが発展していたので、2つの解析プログラムを同時に入れておくことが余分なことだったからです!

この問題には悩まされました。しかし私にはインスピレーションがありました: fetchmailcocnf に fetchmail 自信の解析プログラムを使用するのです!そこで、 --configdump オプションを加えました。これは .fetchmailrc を解析して 結果を Python イニシャライザでフォーマットして標準出力にダンプします。上記ファイルの例を Listing 2 で見ることが出来ます(スペースを節約するために、参考例に関連していないデータは省略されています)。

Listing 2

これで Python によって fetchmail --configdump の出力を評価できるようになりました。そして、変数 fetchmail の値として設定を利用できるようにしたのです。

ここでもまだダンスの最後のステップに到達したわけではありません。私が本当に望んだことは fetchmailconf が現存の設定ファイルを持たないことでした。つまりオブジェクトのツリーへリンクを貼ることではないのです。このツリーには3種類のオブジェクトがあります: 構成 (全体の構成を表すトップレベルのオブジェクト)、 サイト (調査するサイト1つを表す)、 ユーザー (サイトに添付されるユーザーを表す)。例に挙げたファイルには5つのサイト・オブジェクトと、サイトそれぞれに添付されるユーザー・オブジェクトが書いてあります。

私は早々と3つのオブジェクト・クラスを設計して書きました(この作業には4日かかりました。そのほとんどはウィジェットのレイアウトに費やしました。) 例のデータを修正するために GUI 編集パネルがポップアップするよう、それぞれのメソッドを持っています。最後に残った問題は、なんとかして Python イニシャライザを使って死んだデータを本物のオブジェクトへ変換させることでした。

3つのクラスすべてがその構造と仕様に関して明快に区別できるようにイニシャライザを通して調和するオブジェクトを作成するようなコードを書くように考えました。しかし、言語が成長するとともに時が経つにつれてクラスのメンバが加えられそうだったのでその考えを捨てました。もしも当たり前のようにオブジェクトを作成するコードを書いていたら、こわれやすく、そしてクラス定義やイニシャライザの構造のどちらかが変化したときに同時性を損なう傾向があるでしょう。

私が何を望んだかというと、イニシャライザの型とメンバを分析し、それらのメンバについてクラス定義自体に疑いをかけ、そして2つのセットとインピーダンスマッチそのものを調整するコードでした。

この種の考えはメタクラス・ハッキングと呼ばれ、一般的には恐ろしいほどの奥義であると考えられています--神秘的な黒魔術。ほとんどのオブジェクト指向言語はこれを全くサポートしません;これが出来るものでは( Perl がそうです)、かなり込み入っていて壊れやすい仕事なので注意が必要です。私は今までのところで Python の低い不和率に感動させられましたが、ここに本当のテストが待ち構えていました。メタクラス・ハッキングのためにどのくらい熱心に私はこの言語と格闘する必要があるのでしょうか?勝ったと仮定しても以前の経験からこの勝負は苦しくなることは解っていました。しかし、本へ飛びついて Python のメタクラス機能を研究したのです。この成果は Listing 3 で見ることが出来ます。そしてそれを呼び出すコードは Listing 4 にあります。

Listing 3

Listing 4

残念ですが神秘的な黒魔術には見えないでしょう?コメントを含めて32行あります。クラス構造について先に話したので呼び出すほうのコードは判読しやすいと思います。しかしこのコードのサイズに本当のショックを受けたのではありません。よく聞いてください: このコードを書くのに90分掛かりました。--そしてこれが一発で正常に動作したのです。

私が驚いたと言うことが、確かに控えめな言葉に聞こえるかもしれません。6日間、新しい言語でゼロから始めたメタクラス・ハックにおいて、シンプルなテクニックの実装が1回で予想したように動作することは十分注目に値する出来事でしょう?私がみなさんから才能のあるハッカーだと規定されているとしても、これは Python のデザインの明快さと優美さに驚くべきことなのです。

言語に関する私の経験とレベルを持ってしても Perl でこれを実現できた方法はひとつもありません。Perl を卒業したのは恐らくこの事がポイントだったのでしょう。

さて、これが私がもっとも驚いた瞬間でした。しかしそれはただの器用なハッキングに過ぎません。言語の長期的な有用性はハッキングを助けることではなく、 日々のプログラミングの仕事をたっぷりと控えめにどれだけサポート出来るかに掛かっています。プログラミングの仕事はほとんどが既存のものを修正します。新しいプログラムはあまり書きません。

ですから本当の話しのオチはこうです: fetchmailconf を書いた数週間、数ヶ月後に、私はそのコードを今まで通り何の苦労もなく読めたのです。小さなプロジェクト以外は決して Perl では何も書かないと思っていたときにも大きなコードを書いていました。私はいつか keeper と anthologize を修正することを恐れています。-- fetchmailconf はいかなる心配も与えません。

まだ Perl には用途があります。多くのテキスト・パターンの照合を含んだ小さなプロジェクト(100行かそれより少数)では Python より、 私はまだ Perl の regexp で解法を遊び半分でいじくり回すでしょう。最近の良い例としては、 timeseriesgrowthplot というスクリプトが fetchmail の中にあります。実際にはこれらは Perl が awk/sed/grep/sh を組み合わせたように機能するものであり、そしてオペレーティングシステムの API へのアクセスを指示します。より大きく複雑なものに関しては、私は Python の微妙な徳を好むようになりました--あなたもそうするだろうと思います。

この記事で参照されたすべてのリストがダウンロードできます。ftp://ftp.ssc.com/pub/lj/listings/issue73/3882.tgz

エリック・レイモンド は Linux の支持者であり『伽藍とバザール』の作者でもあります。彼とはEメールで連絡を取れます。esr @ thyrsus.com

原文の URL は: http://www.linuxjournal.com/article/3882


変更履歴

2010年1月30日
リンク先が変更されたURLを修正
2006年5月21日
誤植を修正
2006年5月13日
  • リンク先が変更されたURLを修正
  • 書籍 Programming Python へのリンクを追加
  • 冒頭文の誤訳を修正
2005年6月28日
誤字脱字を修正
2002年12月25日
初版公開

最終更新日: 2006年05月21日(日) / カテゴリー: プログラミング・ソフトウェア開発


Back to top