Next: , Previous: Instrumenting Macro Calls, Up: Instrumenting Macro Calls


17.2.15.1 仕様リスト

マクロ呼び出しの引数のあるものは評価し別のものは評価しない場合には、 edebug用仕様に仕様リスト(specification list)が必要になります。 複数の引数に一致する仕様リストの要素もありますが、 後続の要素の処理を修飾する要素もあります。 後者は仕様キーワード(specification keyword)と呼ばれ、 (&optionalのように)‘&’で始まるシンボルです。

仕様リストには、それ自体がリストである引数に一致する部分リストや グループ化に使うベクトルを含んでもかまいません。 部分リストやグループは仕様リストを階層に分けます。 仕様キーワードはそれらを含む部分リストやグループの残りに適用されます。

仕様リストに選択肢や繰り返しが含まれる場合、 実際のマクロ呼び出しに一致させるにはバックトラックが必要な場合もあります。 詳しくはSee Backtracking

edebug用仕様では、正規表現による一致と文脈自由文法の構文を使えます。 対応した括弧に囲まれた部分リスト、フォームの再帰的処理、 間接仕様による再帰です。

仕様リストの要素に指定できるものとそれらの意味を以下に示します。

sexp
処置しない評価しない1つのLispオブジェクト。
form
処置した評価する1つの式。
place
Common Lispのsetf構文のように値を格納する場所。
body
&rest formの省略形。 以下の&restを参照。
function-form
関数フォーム。 クォートした関数シンボル、クォートしたラムダ式、 あるいは、(関数シンボルやラムダ式に評価される)フォーム。 これは、ラムダ式である引数が、 functionではなくquoteでクォートされるときに有用である。 というのは、ラムダ式の本体をいずれかの方法で処置するからである。
lambda-expr
クォートしていないラムダ式。
&optional
この仕様リスト内の後続の要素すべては省略可能。 一致しないと、edebugはただちにこのレベルの一致を止める。

数個の省略可能な要素に省略不可な要素を続けるには、 [&optional specs...]を使う。 数個の要素がすべて一致するかまったく一致しないことを指定するには、 &optional [specs...]を使う。 以下のdefunの例を参照。

&rest
この仕様リスト内の後続の要素すべてを0回以上繰り返す。 最後の繰り返しでは、仕様リストの要素すべてに一致するまえに 式を使い尽くしても問題にはならない。

数個の要素のみを繰り返すには[&rest specs...]を使う。 各繰り返しですべてが一致するような数個の要素を指定するには、 &rest [specs...]を使う。

&or
仕様リスト内の後続の各リストは選択肢を表す。 選択肢の1つに一致しなければ、仕様&orは失敗。

&orに続く各要素は1つの選択肢を表す。 複数の要素を1つの選択肢としてグループにまとめるには、 それらを[...]で囲む。

&not
&orを使ったかように後続の要素を選択肢として一致させるが、 どれかが一致すると仕様は失敗。 どれにも一致しなければ、仕様&notは成功。
&define
仕様は定義フォームに対するものであることを表す。 定義フォームそのものは処置しない (つまり、edbugは定義フォームの前後で停止しない)が、 この内側にあるフォームは典型的には処置される。 キーワード&defineはリスト仕様の最初の要素である必要がある。
nil
現在の引数リストのレベルにおいて一致する引数がなければ成功する。 さもなければ失敗。 部分リスト仕様と以下のバッククォートの例を参照。
gate
いかなる引数とも一致しないが、このゲートを通ると、 このレベルの仕様の残りの部分と一致を調べる際には バックトラックを禁止する。 これは主により詳しい構文エラーメッセージを生成するために使う。 詳しくはBacktrackingを参照。 例については以下のletを参照。
その他のシンボル
仕様リストのその他のシンボルは述語であるか間接仕様である。

シンボルにedebug用仕様があれば、 この間接仕様は、シンボルのかわりに使われる仕様リストであるか、 引数を処理するために呼び出される関数であること。 仕様は、マクロ向けにdef-edebug-specで定義した仕様であってもよい。 以下のdefunの例を参照。

さもなければ、シンボルは述語であること。 述語は引数で呼び出され、述語がnilを返すと仕様は失敗する。 いずれの場合でも、当該引数は処置されない。

適当な述語には、symbolpintegerpstringpvectorpatomがある。

[elements...]
要素のベクトルは要素群を単一のグループ仕様にまとめる。 この意味はベクトルの意味とは関係ない。
"string"
引数はstringという名前のシンボルであること。 この仕様は、symbolの名前がstringである クォートとしたシンボル'symbolと等価であるが、 文字列のほうが望ましい。
(vector elements...)
引数は、仕様内のelementsに一致するものを要素とするベクトルであること。 以下のバッククォートの例を参照。
(elements...)
その他のリストは部分リスト仕様であり、 引数は仕様elementsに一致するものを要素とするリストであること。

部分リスト仕様はドット対リストでもよく、その場合、 対応するリスト引数はドット対リストである。 あるいは、ドット対リスト仕様の最後のcdrは ((spec . [(more specs...)])などの グループや間接仕様を介した) 別の部分リスト仕様であってもよいが、 それらの要素はドット対ではないリスト引数に一致する。 これは、以下のバッククォートの例のような再帰仕様に有用である。 このような再帰を終らせるうえの仕様nilも参照。

(specs . nil)(specs . (sublist-elements...))のような部分リスト仕様は (specs sublist-elements...)と等価であることに注意。

&defineのうしろに追加できる仕様の一覧を以下に示します。 以下のdefunの例を参照してください。

name
引数はシンボルであり、定義フォームの名前である。

定義フォームには単一の名前フィールドがある必要はなく、 複数の名前フィールドを持っていてもよい。

:name
この構造は引数には実際には一致しない。 :nameに続く要素はシンボルであること。 定義に対する追加の名前要素として使う。 定義の名前に一意で静的な要素を追加するために使う。 複数あってもよい。
arg
引数はシンボルであり、定義フォームの引数の名前である。 しかし、ラムダリストキーワード(‘&’で始まるシンボル)は許されない。
lambda-list
ラムダリスト、すなわち、ラムダ式の引数リストに一致する。
def-body
引数は、定義内のコード本体である。 これは、上に述べたbodyに似ているが、 定義本体は定義に関連した情報を調べる異なるedebug呼び出しで処置する必要がある。 定義内のフォームの最上位レベルのリストにはdef-bodyを使う。
def-form
引数は、定義内の単一の最上位レベルのフォームである。 これはdef-bodyに似ているが、 フォームのリストではなく単一のフォームに一致するものに使う。 特別な場合として、def-formは フォームを実行したときにトレース情報を出力しないことを意味する。 以下のinteractiveの例を参照。