SchemeAndImpl / 1.Overview


SchemeAndImpl

概観

この本では、プログラマー -- とは言っても、初めてプログラムするというわけでなくて、すでにプログラムのやり方は(少なくとも少しは)知っていて、興味を持ってSchemeを学ぼうとする人たちに、Schemeを紹介していきます。

Scheme: 小さいけれど強力な言語

[この導入部はblatherに改良する必要がある*1]

Schemeは、きれいでとても小さく、しかし力強い言語で、汎用的なプログラム言語としてもふさわしいし、スクリプト言語としても、アプリケーションに組み込む拡張用言語としても、他のどんなことにもふさわしい言語です。

Schemeは、多様な実装がされるようにと考えてつくられ、そして多くの実装が存在します。それらの多くはフリーのソフトウェアです。そのまま動くインタープリタ(BASICやTclのように)もありますし、速い機械語へとコンパイルするコンパイラ(CやPascalのように)もあり、インタープリタ上で走る中間的なコードを生成するコンパイラ(Javaのように)もあります。

Schemeのいくつかの拡張された実装には、われわれのRSchemeシステムも含みますが、統合的なオブジェクトシステムや力強い拡張性を備えた、非常に可搬性のあるSchemeの実装があります。

このドキュメントは、Scheme、Schemeの実装、RScheme言語とその実装と続く3部作のうちの初めのものです。それらが全部終わったときには、大きな本にまとめようとしています。3つともすべてTexinfo*2形式として、マニュアルとして使用するために紙にも出力できるし、オンラインでドキュメントとして読む(Info BrowserだったりEmacsエディタのInfoシステムを通じてとか)のもいいし、Webブラウザ用に自動的にHTML形式に変換したりもできるでしょう。どのようにしてあなたがこれを読むにしても、Schemeへようこそといいたいです。

[注:現時点の草稿はpostScript形式でのみ利用可能です。なぜなら外部情報やHTMLバージョンのハイパーリンクをまだすべて行なっていないので]*3

この本はどんな人向けか

この本は、ただSchemeを使うことに興味がある人のためはもちろん、Schemeがどのように動くのかに興味がある人たち、プログラミング言語のデザインといった見地でSchemeに興味がある人々向けにも書かれました。

これらの目的の間にはそんなに矛盾はないのです。というのは、Schemeを学ぶのに最善のの手段のうちの1つは、-- そして言語のデザインの重要な原則でもありますが -- SchemeがSchemeでどのように実装されるかを見ることです。いくつかの簡単なSchemeのサブセットのインタープリタと、簡単なコンパイラを提示することにより、Schemeのパワーを見てもらおうと思います。

Abelson と Sussman の 計算機プログラムの構造と解釈 *4 という広く使われたプログラミングへの導入テキストでも取られた手段ですが、これは非常に伝統的なアプローチです。このアプローチは多かれ少なかれ他のいくつかのSchemeプログラミングの入門書でも取られています。ですが、これらの本の大半は初心者のためのものです。私は、Schemeは偉大な最初の言語だとおもっているのですが、多くの人々がCやパスカルなどにかまっていて、Schemeを探検的に学ぼう*5などと入門書を読んだりもしてくれません。

私のアプローチはSchemeについて現在刊行されている書籍の大半とは、いくつかの点で異なっています。 [書き終えたとき、この本はハイパーテキスト化となり、相互参照を付けてオンラインで手軽にみることのできるようになる予定です]

基本的なプログラミングの考え方についてはざっと流すつもりです。例えば、変数がなんなのか、再帰とは何なのか、こういったことについて、あなたが何かしらを知っているものと仮定しています。

Schemeについて多くある書き方よりは、もっと具体的なアプローチを取ります。なぜなら、その方が学生たちが理解 しやすいと分かったからです。そこかしこで、言語のレベルの底流にずっと降りて行き、どのように実際の実装が行なわれているかをお伝えするつもりです。この具体性こそが多くの学生の心で漠然としがちな理解を助けるものなのです。私自身も含め。

ここでは、Schemeは式を書き換えることによって実行を進めていく、というような関数的プログラムからはスタートしません。(何をいっているのか分からなければ、まったく気にしないでいいことです!)

Schemeを弱いオブジェクト指向の手続き型言語のなかの特殊ケースとしてとらえてみます。

継承やその他の特徴を持っていないために弱いオブジェクト指向だと言っているわけではありませんし、いくつかの拡張されたSchemeはその特徴を持っています。 私が意味しているのは、言語における値が、そのIDが重要であるデータオブジェクト(レコードなど)であり、オブジェクトが可変の状態を持つことができるという点においてです。IDが重要というのは、2つのオブジェクトがまさしく同じものかを判定する際に、それらの状態を比べるだけでなく、ポインタを比べることができるということです。(この観点はRSchemeではさらに推し進められ、完全にオブジェクト指向言語となっていて、同時にSchemeでもあるということになっています。ですが、そのことについては、まだ書かれていない別の本にて。)

私が最初から状態や代入のことを話すので、このアプローチを好まない人がいるかも知れません。Schemeにおいては、代入を自由に使用する8のは一般に悪いスタイルだと考えられているからです。良いスタイルというのは、大体において、「関数的」で「応用的」なプログラムだと考えられています。大部分が関数的なプログラミングが、通常はSchemeにおいて正しいことであることは、私も同意しますが、そうしない意図は言語の意味論を初めのうちからクリアにしておきたいためであるのと、新人のSchemeプログラマ(Schemer)にSchemeは別に普通のプログラミング言語だということを明らかにしておきたいためです、普通じゃない面としてはきれいで表現豊かだという点もあるものの。Schemeを教えてきた私の経験から確信しているのですが、代入の使用を早いうちから教えてしまうのは、多くの人にとって益のあるものでした。というのは、そのことにより、変数と変数の束縛(binding)*6が明らかにできるからです。スタイルについては後で、代替案がはっきり出てきてから、議論するとしましょう。

もし、LispやSchemeを以前に学ぼうとして、あまり進まなかったのなら、この本はあなたのためかも知れません。LispやSchemeにごく自然に取り組める人も多いのですが、なかにはそうでない人もいます。私が思うに、それは素材がどのように紹介されたかによるのではないでしょうか。LispやSchemeを学ぶのに難しいことはないのです。この本では、これまで説明されてきたやり方とはちょっと違ったふうに物事を説明していくつもりです。大半の本でつまづいてしまう人たちが、そういった種類の問題にぶつからないように。 説明が具体的であるので、これらの言語におぼえるとっつきにくさは軽減されるでしょう。Schemeはただ本当に普通のプログラミング言語なのです。ただその強力な特徴は特別なやり方で使われたりすることもあるだけです。

もしあなたがプログラミング言語をデザインする人であって、でもSchemeやLispにはそれほど親しんでいないというなら、この本はこれらの言語の全体像を明らかにしてくれる助けとなるかも知れません。Lispの世界と「基礎的な(conventional)」プログラミング言語帝国の間には、大きな溝があるというのが私の信じるところですが、これは大体が違うコミュニティが違った語彙を使っていることによるのです。Schemeにおける最近の発展は、他の言語のデザイナーにも広く評価されたわけではありません。(このテーマはこのシリーズの別の文書で深く掘り下げたいところです。) Lispの古くからの特徴、マクロなどですが、これらは一般の言語デザイナーに的確に理解されては来ませんでした。その問題はSchemeにきて本質的に解かれたと思います*7

もしあなたがプログラミング言語を実装する人なら、あるいはプログラミング言語の実装を教える人なら、この本は役に立つかも知れません。(私は、言語と実装についての課程で、この本を使います。) Schemeのためのインタープリタとコンパイラを提供します。Schemeは言語実装の原則を教えるには、優秀な乗り物です。その統辞論はシンプルで、簡単なインタープリタからより複雑なものへと直線的に進化していけますし、同じように直線的に進化していってコンパイラにもなります。これにより、関係ない瑣末事に立ち入るのを極力少なくして、言語実装の原則について教えることに役立ちます。

なぜSchemeか

[狂信的なScheme党員みたいに見えるかも知れないけど…]

Schemeは言語を実装するために、あるいは一般に変容的プログラミングにおいて -- つまり、プ ログラムを書くプログラムを書くということ --、あるいは簡単に拡張したりカスタマイズできるプログラムを書くためには、とてもうってつけの言語です。Schemeを実装するために使用する にあたり、Schemeを魅力的なものにしている特徴は、スクリプトを書くことや、新しい言語を構 築すること、アプリケーションに特化したプログラム環境を作ることなど、すべての種類の事柄 において役立ちます。

[Schemeを学ぶにつれ、すべての興味深いプログラムが、結果として、アプリケーションに特化した環境を形作っていることに多分気が付くでしょう。]

大抵のSchemeシステムは会話的で、自分のプログラムの部分部分を、漸増的に開発し、テストす ることができます。この点では、BASICやTclのようです -- ずっときれいで表現力は豊かですが 。Schemeはまたコンパイルすることもできますし、そうすれば速く走るようになります。このこ とにより、作り込むにはBASICやTclのように簡単で、でもCのように速くなります。(Schemeは通 常Cほどは速くありませんが、よいSchemeコンパイラがあるなら、遅すぎるということはありません。)

大抵の会話的言語と違って、Schemeはうまく設計されています。それは、当初非常に限られた応 用範囲で考えられた寄せ集めだったり、あとで拡張されてきたりしたものではありません。それ は初めから一般的な目的のための言語として設計されて、2つの早期の言語の最良の特徴を組み合わせたものです。それはLispの根本的な見直しであり、LispとAlgol(C,Pascalなどの祖先)両方の最良の特徴を組み入れたものです。

(これがSchemeが、TclやPerlといった寄せ集め的な言語の代わりとして、あるグループに採用された理由です。Free Software FoundationのGuile拡張言語はSchemeを基礎としています。UnixのShellであるScheme Shell(scsh)にしてもそれは同様です。CAD Framework Initiativeは SchemeをCAD*8ツールをコントロールするつなぎとしてSchemeを採用しました。Dylan言語も、違う統辞論や多くの拡張を持っていますが、これもまたSchemeを基礎としています。)

もしLispを学びたいのであれば、Schemeはスタート地点としてよいところです。Common Lisp は大きく、どこかややこしい言語で、それを学ぶにはSchemeから学ぶのが一番簡単な道だと思われます。そうすれば、Common LispがSchemeの拡張(extenstion)シリーズ(そして大いなる混乱)だと分かるでしょう。Common Lispの最良の特徴のなかには、Schemeからコピーされたものがあります。

もし、関数的*9プログラミングがどういうものか知りたいのであれば、Schemeでそれをすることができます。多くの興味深いことを行うには関数的プログラミングが一番やさしいやり方であるために、大体のよく書かれたSchemeプログラムは大いに関数的となっています。

それから、あなたがただプログラミングをもっとうまくやりたいということで学ぶのであれば、Schemeはプログラムについての考え方に新しい目を開いてくれるかも知れません。多くの人たちがSchemeでプロトタイプを作成します。というのは、それがとても簡単だからなのです。たとえそれを雇い主を満足させるために、別の言語で書き直さなければならない場合においてさえ同じことです。

なぜ今Schemeなのか*10

Schemeは新しい言語ではありません--それは20年間の間、ゆっくりと進化してきました。

Schemeの進化はゆっくりだったのは、Schemeを標準化する人々がとても保守的だったからです-- 言語の特徴はその動き方について全体の同意が得られて始めて、標準化されました。焦点は質にあり、産業的に使用しやすいかではなかったのです。

この方針は2つの結果を招きました。1つは、Schemeが美しく、段違いによく設計された言語であることです。2つ目は、Schemeは「最適化からは遠かった(behind the curve)」*11、汎用的な言語として役に立ついくつかの特徴に欠けていました。しかし次第にSchemeはとても小さな言語から、概念を教えるというためには、とても役立つ言語として育って来ました。

Schemeでもっとも重要な新しい特徴は、(私の観点では)静的スコープを持つ「衛生的」マクロ*12で、それにより、多くの言語特徴を可搬的で、非常に有効なやり方で実装することができました。このことにより、Schemeは小さいままでいながら、有益な拡張もライブラリとして書くことができ、さしてパフォーマンスにも影響がないということができたのです。


この本で扱っていないこと

この本は、Scheme言語の定義をするものでもないですし、特定のScheme言語実装を使うためのマニュアルでもありません。Scheme言語の定義ドキュメントとしては、フリーのものが、簡単にインターネット軽油で入手でき、それは「アルゴリズム言語 Scheme 報告書」 (Revised Scheme Report)*13と呼ばれるものです(IEEE標準も存在します)。Scheme報告書を入手して、印刷しておくことをおすすめします。あるいはHTML版をWebブラウザで見るのでもよいですが。(http://www.cs.indiana.edu/scheme-repository/doc.standards.html Schemeがとても小さい言語なので、文書もあまり大きくないです。ご自分の使っているSchemeの特定の実装のドキュメントにも目を通しておくことをお勧めします。*14)

その一方で、この本は言語のマニュアルへの橋渡しとしては役立つのではないかと思います。(この目的のためには、もっと肉付けしてオンラインのインデックスをもっと充実させたら、よりよくなるでしょう。)標準的なSchemeの重要な特徴がすべて、大体の使用目的には適うように、十分明解に説明しています。これが可能なのは、Schemeがとてもきれいで「直交的」です、ーー つまり、多くの特徴が変な相互干渉を起こしたりはしていないのです。なので、Schemeを理解するのであれば、そして「Scheme的(Scheme-ish)」なことをしたければ、Schemeはあなたの期待したことを普通に行うでしょう。

Schemeや特定のSchemeの実装などについてもっと情報が欲しければ、usenetのニュースグループ comp.lang.scheme に、FAQリストを見てください。それは、ftp.cs.indiana.eduのディレクトリ pub/scheme-repository から anonymous ftp 経由で、Schemeレポジトリが入手可能です。(2009年4月の現状について訳者注:*15) あるいは、WWWユーザなら、http://www.cs.indiana.edu/sche me-repositoryにも、Schemeレポジトリがあります。SchemeレポジトリはいくつかのSchemeのフリー実装を含んでいて、役立つプログラムやライブラリ、記事などもいろいろあります。

この本の構成

この本の構成には、概念ごとにグループ化しているというよりは、教材(tutorial)用の意図が反映されています。次の3つの章では、私が学びやすいだろうと思う順にアイデアを紹介していきます。各々の章はいくつかの関連するアイデアを、小さなコード例とともに紹介し、終わりには、なぜそのアイデアが役立つのかを見せるためにもっとSchemeのプログラム例を出します。その後の章では比較的に独立した主題を紹介することになります。

[この後に書いていることは、実際のドキュメント構造を決めた後に、少し手直しが必要となる。]

導入では、Schemeの基本的な特徴をいくつか描き出し、少し統辞論や、Schemeが大方のプログラミング言語と同じく使えること--つまりSchemeを使う上であきらめなければならないことはあまりなくて、切り替えるのは難しくはないということを示すために、いくつかコード例を出すことにします。

Schemeを使ってみる(チュートリアル)では、Schemeプログラミングを実際にやってみること、Schemeシステムが実行されている環境で、会話的に例を試してみるということをしてみます。

インタプリタを書いてみるでは、Schemeのサブセット用の簡単なインタープリタを書いてみます。

環境と手続き?では、Schemeでの環境と手続きの束縛について説明し、どのように手続的な抽象(procedural abstraction)が、ファーストクラスの手続きと限りなく広がっていくブロック構造(ガーベッジ・コレクション)を持った言語の中では、とても強力となることを示します。*16

そして、環境と手続きの束縛を、前の章でのインタープリタに実装することと、Schemeの束縛と手続きを定義する構造を、洗練されたやり方でどのように使っていくかを提示したいと思います。

Schemeにおける再帰?では、再帰を、特に末尾再帰を扱います。

準引用式とマクロ?では、複雑な式や、決まりきったデータ構造の色々を構築する手段として、準引用式を見ていき、それからマクロをあなた自身の「特殊形式」をScheme内で定義するための手段として見ていきます。 マクロで、あなた自身の構造、オブジェクトシステムのようなデータ構造システムなどを定義することができるようになります。 (C とか Lisp のマクロで挫折したことがあったとしても、心配しないでください。Schemeのマクロは古いマクロ体系の主要な問題を修正しています。) マクロにより、実装がレイヤーで構造化されます。その言語自身で実装されている言語がそうであるように、コンパイラが理解できる小さいコアの言語から、どんどん増殖して起動されていきます。

他の有益な特徴?では、Schemeが実際のプログラムを書くにあたって有益であるその他の特徴をいろいろ見ていきます。Schemeの概念的なコアではないのですが、役に立つ言語というのは、そういう特徴を備えているものです。

レコードとオブジェクト指向?は…*17

現在の継続と共に呼ぶ(call-with-current-continuation)? では、ファーストクラス*18の「継続」、Schemeにおいてもっとも強力な制御構造について取り上げます。継続により、アクティベーション・スタック(のようなもの)の状態を捕まえることができます。そして、その状態に戻って、プログラム実行のある時点からまた実行を再会することができます。継続は概念的には変な感じで、そうそう気軽に使えるものでもないですが、バックトレースやスレッドなどの事柄を扱うには、びっくりするほど表現豊かに使えます。

簡単なSchemeコンパイラ?は、Schemeの簡単なコンパイラまで育ってしまったSchemeプログラムの例をお見せします。それは「おもちゃの」コンパイラで、本物のコンパイラではないのですが、基本的なSchemeコンパイラの特徴はすべて備えていて、でもトークン切りや、記憶領域管理などのつまらない「周辺の」技術(hack)については最小に留めています。

(了)



*1 訳注:意味がよく取れないが、「長々しくしたほうがいいかな」ぐらいの意味ではなかろうか。
*2 訳注:あまり詳しくないですが、TeXで処理できる形式
*3 訳注:私は今見ているHTML版しか見つけていません。
*4 Structure and Interpretation of Computer Programs 参照:http://www.nilab.info/wiki/SICP.html
*5 wade through 困難に分け入る
*6 この「束縛」ではなく「割り当て」という訳語がふさわしいとする日本人Lisperもいます。
*7 訳注:その古くからの評価されてこなかった特徴が、Schemeで前面に出てきて分かりやすくなった、という意味にとれる
*8 コンピュータ援用設計
*9 funcional 機能的と訳したほうがしっくりくる場合もあるのですが、いわゆる「関数」との互換性のため、関数的としています。
*10 訳注:2000年以前に書かれた雰囲気があるので、「今」が2009年を意味する訳ではないことにはご注意ください。
*11 もっといい訳がありそうです
*12 lexically-scoped ("hygeinic") macros
*13 最新版は、六訂版だったはず(2009年4月現在)。[アルゴリズム言語 Scheme 報告書 五訂版]は、http://www.unixuser.org/~euske/doc/r5rs-ja/で閲覧可能。Yusuke Shinyama氏に感謝。
*14 訳者の経験では、MzSchemeを落としてきたら、それにR5RS(英語の五訂版)が付いてきました。
*15 http://www.cs.indiana.edu/scheme-repository/home.htmlが最新であり、このテキストて示してあるftpサイトも存在していますが、「メンテナンスしていないので、最新サイトを参照してください」とREADMEに書いてありました。
*16 内容が分かっていないので、的外れな訳になっている可能性があります。ご意見あればコメントにお願いします。
*17 私の持っている版ではここで終わっています。
*18 私の場合、ルート・レベルといった理解です。