[Contents]   [Back]   [Prev]   [Up]   [Next]   [Forward]  


2. Schemeの概要

2.1 言語仕様

この節では、Schemeの言語仕様の概要を説明する。厳密な形式にこだわらない文法については、section 4. 基本概念からsection 7. 標準手続きで詳しくとり扱う。Schemeの言語形式については、section 8.2 形式記号言語で説明する。

Algolを継承したSchemeは、静的スコープを持つプログラミング言語である。使用する変数は一つ一つ、辞書的に明らかなその変数のバインディング(5)と連結される。Schemeは明示的な型とは逆の、暗黙の型を持っている。型は変数とではなく、(オブジェクトとも呼ばれる)値に連結されている。(著作物によっては暗黙の型を持つ言語を、弱い型生成を行なう言語、もしくは動的な型生成を行なう言語と呼ぶ場合がある。)暗黙の型を持つ言語には他にAPL、Snobol、およびSchemeとは別のLisp方言がある。明示的な型を持つ言語(強い型生成を行なう、もしくは静的な型生成を行なう言語と呼ばれる場合もある)にはAlgol 60、Pascal、Cが含まれる。

Schemeの演算過程で作成されるオブジェクトはすべて無限エクステント(6)を持つ。オブジェクトには手続きとコンティニュエーションが含まれる。Schemeのオブジェクトは廃棄されることが決してない。Schemeの実際の処理系が(通常は!)メモリ不足に陥ることがない理由は、あるオブジェクトが将来の計算に関係することがあり得ないと証明できた場合に、そのオブジェクトが占有している記憶域をSchemeが回収できるからである。ほとんどのオブジェクトが無限エクステントを持つその他の言語には、APLとScheme以外のLisp方言が含まれる。

Schemeの処理系は、正しく終端再帰を行なうものでなければならない。これにより、繰り返し計算が構文上再帰手続きで表現された場合でも、繰り返し計算を一定の空間内で行なうことができる。したがって終端再帰を実装していれば繰り返しを通常の手続き呼び出し機構で表現できるので、特別な繰り返し構造は構文上の味付け程度の有用性でしかない。section 4.5 正しい終端再帰参照。

Scheme手続きは、それ自身がオブジェクトである。手続きは動的に生成でき、データ構造に保存でき、手続きの結果として手続きを返すというようなことができる。このような特性を持つその他の言語には、Common LispとMLが含まれる。

Schemeの際だった特徴はそのコンティニュエーションにある。コンティニュエーションの動作はScheme以外の言語では隠れていて見えず、これは"第一級の"ステータスということもできる。コンティニュエーションは、大域脱出、バックトラッキング、コルーチンを含む、広範囲の先進的制御構造を実装する場合に有用である。section 7.4 制御機能参照。

Scheme手続きの引数は、必ず値で渡される。これは、手続きが評価の結果を必要とするしないにかかわらず、手続きに渡される前に実引数が評価されることを意味する。Scheme以外の言語ではML、C、APLの三言語が引数を常に値で渡す。これはHaskellの遅延評価文法や、Algol 60の名前渡し文法とは異なっている。この二つの言語では、手続きが値を必要としない限り引数の式は評価されない。

Schemeの演算モデルは、コンピュータ内部で数値が表される特定の方法に、可能な限り依存しないように設計されている。Schemeにおいてはすべての整数は有理数であり、すべての有理数は実数でありすべての実数は複素数である。したがって整数と実数の演算を区別することは、多くのプログラミング言語では重要であるが、Schemeには発生しない。それに代わってSchemeには、数学的な観念に対応する完全数の演算と、近似に基づく不完全数の演算の区別が存在する。Common Lispと同じように、完全数の演算は整数に限定されたものではない。

2.2 構文

ほとんどのLisp方言と同じくSchemeも、プログラムと(プログラム以外の)データについて、数がつりあった開き括弧と閉じ括弧を冠する記法を採用している。Schemeの文法では、データに使用された言語の下位言語が生成される。この単純で一様な表現から、Schemeのプログラムとデータは別のSchemeプログラムが同一の方法で処理できるという重要な意義が生まれる。例えばeval手続きでは、データとして表現されたSchemeプログラムが評価される。

read手続きは読み取るデータに、構文上ばかりでなく辞書を作成するようにも分解を実行する。read手続きは、入力をプログラムとしてでなくデータとして解析する(section 4.3 外部表現参照)。

Schemeの構文則はsection 8.1 構文則で説明する。

2.3 記法と用語

2.3.1 プリミティブ、ライブラリ、オプション機能

Schemeのすべての処理系には、オプションとして印をつけていないすべての機能をサポートすることが求められる。処理系はSchemeのオプション機能を省略することも、拡張を追加することもできる。ただし拡張は本報告書のScheme言語と矛盾しないこととする。特に、実際の処理系は移植性のあるコードをサポートしなければならない。したがって処理形の構文構成法は、本報告書の辞書的な規約を恣意的に変更するものであってはならない。。

Schemeの理解と実装を容易にするために、機能の中にはライブラリの印をつけているものがある。ライブラリの機能は、別の機能すなわちプリミティブを使用して簡単に実装できる。これはことばの厳密な意味では冗長なものであるが良く使われるパターンを処理するものであり、適切な省略形を提供するものである。

2.3.2 エラー状況と不定の振舞い

エラー状況に言及する時は本報告書では"エラーが発信される"という語句を使用して、実際の処理系がエラーを検出して報告しなければならないことを示す。エラーを検討している際にこのような語句に言及しない場合は、エラーの検出と報告は望ましいものではあるが、処理系はエラーを検出して報告する必要はない。処理系が検出する必要がないエラー状況では、通常は単に"エラー"とだけ言及する。

例えば処理が明示的に指定されていない引数が手続きに渡された場合はその手続きに対するエラーであるが、このような定義域侵害エラーは本報告書ではほとんど言及していない。実際の処理系はこのような引数を含めるように、手続きの定義域を拡張することができる。

実装上加えられたある種の制限のために正しいプログラムが実行を継続できない場合に、処理系がその旨を報告することを許可されている状況を示すために、本報告書では"実装上の制限の侵害を報告する場合がある"という語句を使用する。いうまでもなく実装上の制限はない方がいいが、処理系は実装上の制限の侵害を報告することが望ましい。

例えばプログラムの実行に必要な充分な記憶域が存在しない場合、処理系は実装上の制限の侵害を報告する場合がある。

式の値が"不定である(unspecified)"と言及した場合、その式はエラーを発信せずに何らかのオブジェクトに評価されなければならない。ただしその値は処理系に依存する。このような場合に返すべき値については、本報告書は明示的には指定しない。

2.3.3 見出しの形式

section 5. 式とsection 7. 標準手続きは、見出し形式で構成されている。見出しの一つ一つが言語機能の一つ、でなければ複数の関連機能のグループの一つを表している。ここにいう機能は、文法構造もしくは組み込み手続きのいずれかを表す。どの見出しも、次の形式の見出し行で始まる。

[[カテゴリー]] テンプレート

上記は必要なプリミティブ機能の場合で、それ以外の場合は次のように書く。

[[修飾子つきカテゴリー]] テンプレート

ただし修飾子は、section 2.3.3 見出しの形式で定義したように"ライブラリ"もしくは"オプション"である。

カテゴリーが"構文"の場合、その項目は式の種類を説明するもので、見出し行は式の構文を示す。式の要素には文法上の変数が指定され、これをかぎ括弧で囲う。例えば<式>、<変数>のように書く。文法上の変数は、ソースプログラムテキストの一部を指すと考えてもらいたい。例えば<式>は、文法上有効な式となるあらゆる文字列を表す。次の記法はゼロ以上の<thing>が現れることを示す。

    <thing1> ...

また、次の記法は<thing>が一つ以上現れることを示す。

    <thing1> <thing2> ...

カテゴリーが"手続き"の場合その項目は手続きを説明するものであり、見出し行は手続きを呼び出すテンプレートを示す。テンプレート内の引数名はイタリック体で書く。したがって次の見出し行

[[手続き]] (vector-ref vector k)

は、組み込み手続きvector-refはSchemeのすべての処理系において、引数二つ、ベクタvectorと非負の完全整数k(下記参照)をとるように定義しなければならないことを示す。次の見出し行

[[手続き]] (make-vector k)
[[手続き]] (make-vector k fill)

では、手続きmake-vectorは一つもしくは二つの引数のいずれかをとるように定義しなければならないことを示す。

ある操作に処理が指定されていない引数が与えられた場合、それはエラーである。簡潔に書くために、次の規約を一貫して採用する。引数名がsection 4.2 型の非共有性に挙げた型名でもある場合、引数はその命名済みの型に属するものでなければならない。例えば上記のvector-refの見出し行では、vector-refの最初の引数がベクタでなければならないという指示を示している。以下の命名規約も、型の限定を含むものである。

2.3.4 評価の例

プログラム内で使用される記号"=>"は、"に評価される"と読んでもらいたい。例えば、

  (* 5 8)      =>  40

は、式(* 5 8)がオブジェクト40に評価されることを意味する。さらに詳しく言い替えれば、文字の連続"(* 5 8)"は、初期環境で、文字の連続"40"で外部的に表されるオブジェクトに評価される。オブジェクトの外部表現については、section 4.3 外部表現参照。

2.3.5 命名規約

規約上、常に論理値を返す手続きは。通常"?"で終る。このような手続きは述語関数と呼ばれる。

規約上、以前に代入済みの場所(section 4.4 記憶モデル参照)に値を保管する手続きは、通常"!"で終る。このような手続きは割り当て手続きと呼ばれる。規約上、割り当て手続きが返す値は不定である。

規約上、ある型のオブジェクトを引数にとって別の型のオブジェクトを返す手続きの名前の中には、"->"が書かれる。例えばlist->vectorはリストを引数にとって、要素がもとのリストと同一のベクタを返す。


[Contents]   [Back]   [Prev]   [Up]   [Next]   [Forward]