Previous: Backquote Patterns, Up: Pattern-Matching Conditional [Contents][Index]
pcase
パターンによる分解pcaseのパターンはあるオブジェクトがマッチ可能なフォーム上の条件を表現するだけではなく、それらのオブジェクトのサブフィールドの抽出もできます。たとえば以下のコードにより、変数my-list
の値であるリストから2つの要素を抽出できます:
(pcase my-list (`(add ,x ,y) (message "Contains %S and %S" x y)))
これはx
とy
を抽出すだけではなく、加えてmy-list
が正確に3つの要素を含むリストであり、最初の要素がシンボルadd
かどうかをテストします。これらのテストのいずれかが失敗したら、pcase
はmessage
を呼び出さずに即座にnil
をリターンします。
あるオブジェクトから格納された複数の値を抽出する処理は分割(destructuring)という処理としても知られています。pcase
パターンの使用によりバインディングの分割(destructuring
binding)を処理することが可能になります。これはローカルバインディング(Local Variablesを参照)と似ていますが、互換性のあるオブジェクトから値を抽出することにより、変数の複数要素に値を与えることができます。
このセクションで説明したマクロはバインディングを分割するためにpcase
パターンを使用しています。オブジェクト構造に互換性があるという条件は、そのオブジェクトがパターンにマッチしなければならないことを意味しています。なぜならマッチした場合のみオブジェクトのサブフィールドが抽出可能になるからです。たとえば:
(pcase-let ((`(add ,x ,y) my-list)) (message "Contains %S and %S" x y))
これは最初にmy-list
が正しい個数の要素をもつリストであり、かつ1つ目の要素がadd
か検証せずに、my-list
から直接x
とy
の抽出を行う点を除いて前の例と同じことを行います。実際にオブジェクトがパターンにマッチしない場合には、たとえbodyが暗黙にスキップされることはないとしても、その振る舞いは未定義でありエラーがシグナルされるか、あるいはいくつかの変数がnil
のような任意の値にバインドされた状況でbodyが実行されるかもしれません。
バインディングの分割に有用なpcaseパターンとしては、マッチされるオブジェクト構造の仕様を表現するBackquote Patternsで説明したパターンが一般的です。
バインディングの分割にたいする代替え機能についてはseq-letを参照してください。
bindingsに応じて変数のバインディング分割を行い、それからbodyを評価する。
bindingsは(pattern exp)
という形式のバインディングのリスト。ここでexpは評価する式、patternはpcase
パターン。
expはすべて最初に評価されて、その後で対応するpatternにマッチされて、bodyの内部で使用可能な変数バインディングが導入される。この変数バインディングはpatternの要素を、評価されたexpの対応する要素の値に分割してのバインディングすることにより生成される。
bindingsに応じて変数のバインディング分割を行い、それからbodyを評価する。
bindingsは(pattern
exp)
という形式のバインディングのリスト。ここでexpは評価する式、patternはpcase
パターン。この変数バインディングはpatternの要素を、評価されたexpの対応する要素の値に分割してのバインディングすることにより生成される。
pcase-let
とは異なり(しかしlet*
と同じように)、各expはbindingsの次要素の処理前に対応するpatternにたいしてマッチされるので、各bindingsのいずれかによって導入される変数バインディングはbody内で利用可能になるのに加えて、その後に続くbindingsのexp内で利用可能になる。
繰り返しごとにpatternの変数をlistの要素の対応するサブフィールドに分割バインディングしながら、listの各要素ごとに一度bodyを実行するこのバインディングはpcase-let
の場合のように行われる。patternが単なる変数ならdolist
と等価(Iterationを参照)。