R6RS:翻訳:R6RS:7.1 Library form

R6RS:翻訳:R6RS:7.1 Library form

7.1. ライブラリフォーム

ライブラリ定義は次のような形式をしていなければならない。

(library <library name>
  (export <export spec> ...)
  (import <import spec> ...)
  <library body>)

ライブラリ宣言は以下の要素からなる。

それぞれのライブラリからエクスポートされたその束縛が全く同じ場合(すなわち1つのライブラリで束縛が定義されそれがエクスポートや再エクスポートによりインポートされることで他のライブラリに到達している場合)に限り、識別子を同じローカル名で2つ以上のライブラリからインポートしたり、同じライブラリから2つのレベルでインポートすることができる。上記にあてはまらない場合に識別子が複数回インポートされたり定義されたりまたはその両方が起こることはありえない。ライブラリ内で明示的に定義されたりインポートされない限りは識別子がライブラリ内で可視になることはない。

<library name> はある実装内でライブラリを一意に特定し、その他すべてのライブラリの import 節(下記参照) において大域的に可視である。<library name> は以下の形式をしている。

(<identifier1> <identifier2> ... <version>)

<version> は空もしくは次の形式である。

(<sub-version> ...)

どの <sub-version> も正確な非負の整数オブジェクトを表現していなければならない。空の <version> は () と等価である。

<export spec> はインポートされた束縛や局所的に定義された束縛のうち公開するものに名前をつける。場合によっては外部名が異なることもある。<export spec> は以下のいずれかの形式でなければならない。

<identifier>
(rename (<identifier1> <identifier2>) ...)

<export spec> において <identifier> はライブラリの中で定義されたりインポートされた1つの束縛に名前をつける。エクスポートする時の外部名はライブラリの中での名前と同じである。rename はそれぞれの(<identifier1> <identifier2>)ペアに対して <identifier1>と名前をつけられた束縛を <identifier2> という外部名でエクスポートする。

それぞれの<import spec>はライブラリにインポートされる束縛のセットを指定し、どのレベルでそれらが利用可能になるかを指定し、どのようなローカル名を持つかを指定する。 <import spec> は以下のいずれかでなければならない。

<import set>
(for <import set> <import level> ...)

<import level> は以下いずれかである。

run
expand
(meta <level>)

ここで、 <level> は正確な整数オブジェクトを表す。

<import level>で考えれば run は (meta 0)、expand は (meta 1) の略である。レベルとフェーズについてはR6RS:翻訳:R6RS:7.2 Import and export levels で議論する。

<import set> は別のライブラリからの束縛の集合に名前をつけ、インポートされた束縛に局所名を指定することもできる。 <import set> は以下のいずれかでなければならない。

<library reference>
(library <library reference>)
(only <import set> <identifier> ...)
(except <import set> <identifier> ...)
(prefix <import set> <identifier>)
(rename <import set> (<identifier1> <identifier2>) ...)

<library reference> はライブラリの名前と省略可能なバージョンによってライブラリを特定する。<library reference> は以下のいずれかの形式である。

(<identifier1> <identifier2> ...)
(<identifier1> <identifier2> ... <version reference>)

1つめの <identifier> が for、library、only、except、prefix、rename である <library reference> は ライブラリの <import set> 内にのみ現れることができる。それ以外の場合は <import set>、(library <library reference> )は <library reference> と等価である。

<version reference> を持たない <library reference> (上の1つめのフォーム)は <version reference> が () の <library reference> と等価である。

<version reference> ではそれにマッチする <version> の集合を指定する。<library reference> は同じ名前を持ち <version reference> にマッチするすべてのライブラリを特定する。<version reference> は以下の形式である。

(<sub-version reference1> ... <sub-version referencen>)
(and <version reference> ...)
(or <version reference> ...)
(not <version reference>)

1つめのフォームの <version reference> は少なくとも n 要素の <version> とマッチする。<version> はそれぞれの <sub-version reference> は一致する <sub-version> にマッチする。 and <version reference> は and に続くすべての <version reference> にマッチしたときにマッチする。同様に or <version reference> では or に続く <version reference> のうち1つにマッチしたとき、not <version reference> では続く <version reference> がマッチしない時にマッチする。

<sub-version reference> は以下のいずれかの形式である。

<sub-version>
(>= <sub-version>)
(<= <sub-version>)
(and <sub-version reference> ...)
(or <sub-version reference> ...)
(not <sub-version reference>)

1つめのフォームの <sub-version reference>は <sub-version>とライブラリの <sub-version> が等しいときにマッチする。<= はそれに続く<sub-version> よりもライブラリの <sub-version> が大きいか等しい場合にマッチする。 <= も同じ仕組みである。and <sub-version reference> は後に続く <sub-version reference>がすべてマッチするときにマッチする。同様に or <sub-version reference> は後に続く <sub-version> の中で1つがマッチすれば、 not <sub-version reference> は後に続く <sub-version> がマッチしなければマッチする。

:

version reference version マッチするか?
() (1) yes
(1) (1) yes
(1) (2) no
(2 3) (2) no
(2 3) (2 3) yes
(2 3) (2 3 5) yes
(or (1 (>= 1)) (2)) (2) yes
(or (1 (>= 1)) (2)) (1 1) yes
(or (1 (>= 1)) (2)) (1 0) no
( (or 1 2 3)) (1) yes
( (or 1 2 3)) (2) yes
( (or 1 2 3)) (3) yes
( (or 1 2 3)) (4) no

library reference によって2つ以上のライブラリが特定された場合は、どのライブラリを選択するかは実装に依存して決定される。

不完全な型や、複製された状態のような問題を避けるために、実装は2つのライブラリが同じ識別子の並びを持つ一方で同じプログラム内で共存できないバージョンであるような状況を禁止すべきである。

デフォルトではインポート元のライブラリからインポートしたライブラリがエクスポートしている束縛はすべて可視となっている。その際にはインポートしたライブラリから与えられた名前を介して可視となっている。インポートされる束縛の明確なセットとこれらの束縛の名前は以下に述べる only、except、prefix、rename フォームによって調整することができる。

もし上記の制約を満たしていない場合は構文違反である。

ライブラリフォームの <library body> は定義(definitions)もしくは式(expressions)に分類されるフォームで構成される。あるフォームがどちらに分類されるかはインポートされたライブラリや展開の結果に依存する――R6RS:翻訳:R6RS:10 Expansion process参照。一般的に定義でないもの(R6RS:翻訳:R6RS:11.2 Definitionsのベースライブラリで利用可能な定義を参照)は式である。

<library body> が式を含む必要がない点を除けば、<library body> は <body>(R6RS:翻訳:R6RS:11.3 Bodiesを見よ)と同じである。<library body> は以下の形式でなければならない。

<definition> ... <expression> ...

最初に現れる式よりも begin、let-syntax、もしくは letrec-syntax フォームがトップレベル body がある場合、それらは body に挿入される(R6RS:翻訳:R6RS:11.4.7 Sequencing 参照)。begin、let-syntax、letrec-syntax にラップされた部分式を含むいくつかまたは全ての body は構文抽象(syntactic abstraction) によって定められる(R6RS:翻訳:R6RS:9.2 Macros 参照)。

R6RS:翻訳:R6RS:10 Expansion processで説明される通り変換式と束縛は左から右に評価され作られる。変数定義の式は暗黙の letrec* にあるかのように左から右に評価される。また body 式も変数定義の式の評価の後に左から右に評価される。エクスポートされた変数のそれぞれに対して未使用の場所が作られ、ローカルの対応する変数の値に初期化される。一番最後の body 式の継続に2回戻ってくる場合の作用は不定である。

: ライブラリ構文の中に現れる library、 export、 import、 for、 run、 expand、meta、 import、 export、 only、 except、 prefix、 rename、 and、 or、not、 >=、<= などの名前は構文の一部であり予約されているわけではない。すなわちそれらと同じ名前をライブラリフォームでの使用に影響を与えず、ライブラリ内で別の目的で使うこともできるし、その名前をライブラリにエクスポートしたりインポートすることもできる。

明示的にライブラリからエクスポートされない限り、ライブラリで定義された束縛はライブラリの外では見えない。しかしながらエクスポートされたマクロによってライブラリ内で定義されたりインポートされた識別子が意図せずエクスポートされることがあるかもしれない。つまりマクロは生成するコードにその識別子へのリファレンスを挿入するかもしれないということである。

全てのエクスポートされた変数はエクスポート先とインポート先のライブラリで変更不可能である。従ってもしもエクスポート先もしくはインポート先のライブラリで明示的にインポートされた変数が set! 式の左側に現れた場合は構文違反である。同様に暗黙にエクスポートされた変数はエクスポート先とインポート先のライブラリで不変である。従ってライブラリ内で定義された変数がエクスポートされたマクロで生成されたコードの中で set! 式の左側に現れた場合は構文違反である。同様にライブラリ内で定義された変数が、エクスポートされたマクロで生成されたコードの中で代入された変数への参照が現れた場合は構文違反である。代入された変数とはエクスポート先のライブラリで set! 式の左側に現れる変数の事である。

ライブラリ内で定義されたその他の変数はすべて変更可能である。

 numero rio
More ...