cond* マクロ ¶pcaseの構文が難解すぎると感じる場合は、pcaseの代替としてcond*マクロを使用できます。また、cond*では、pcaseの代替であることとは無関係な、新しい形式の制御フローが提供されています。
The cond* macro is an extended form of the
traditional cond. A cond* expression contains a series of clauses, each of which can use bind* or bind-and* to specify
binding variables, use match* or pcase* to specify matching a pattern as a condition, or
specify an expression as a condition to evaluate as a test.
各節は通常、(condition body…)という形式をとる。
condition は、cond のように Lisp
式である場合があります(条件式
を参照)。あるいは、(bind* bindings…)、(match* pattern datum)、(bind-and* bindings…)、または (pcase* pattern datum) である場合もあります。
(bind* bindings…)
は、節の本体およびそれ以降のすべての節に対して、bindings
をバインドすることを意味します(let* のバインドリストと同様。ローカル変数 を参照)。条件としては、最初のバインドの値が non-nil である場合に真とみなされます。
(bind-and* bindings…) は、節の本体に対してのみ bindings をバインドすることを意味します(if-let*
のバインドリストと同様。条件式
を参照)。条件としては、いずれのバインドも nil
と評価されない場合に真とみなされます。さらに、いずれかのバインドが nil
と評価される場合、それ以降のバインドの値を表す式は評価されません。
(match* pattern datum) は、datum を指定された pattern にマッチさせることを意味します。pattern が
datum にマッチする場合、この条件は真とみなされます。パターンでは、datum のマッチした部分にバインドする変数を指定できます。(pcase*
pattern datum)
も同様の仕組みで動作しますが、pattern には Pcase 構文を使用します。
match* および pcase*
は通常、包含する節全体の実行にわたってバインディングを適用します。ただし、その節が「非終了」を指定するように記述されている場合(後述)、その節のバインディングは
cond* の残りの全域に及びます。
節の条件が真となり、cond*
を抜けるか、あるいは最後の節である場合、その節の本体における最後の式の値が cond*
構文の戻り値となります。
節の最初の要素が t または bind*
形式である場合、あるいは要素が1つしかなくその要素が match* または pcase* 形式である場合、あるいはキーワード :non-exit で終わる場合、この節は cond*
構文を決して抜けません。代わりに、制御は次の節(もしあれば)へと移ります。bind-and*
節を除き、非終了節の body に対して condition
で行われたバインディングは、この cond* 構文内の残りの節へと引き継がれます。
注:pcase* は :non-exit
をサポートしておらず、非終了節で使用した場合は pcase-let
のセマンティクスに従います。詳細は pcase パターンによる構造分解 を参照してください。
マッチング節は (match* pattern datum) のような形式になります。これは式 datum を評価し、パターン pattern(評価はされません)をそれに照合します。
pattern ではこうしたパターンが許可されており、リスト形式のものはその中に他のパターンを含んでいることがよくあります:
_任意の値に一致します。
keywordそのキーワードに一致する。
nilnilに一致します。
ttに一致します。
symbol任意の値にマッチし、その値に symbol をバインドします。このパターン内で既に symbol がマッチしてバインドされている場合、ここでは以前にマッチしたのと同じ値にマッチします。
regexpregexp が一致する場合、文字列にマッチします。マッチ範囲は、文字列の先頭文字から末尾文字まで全体を網羅する必要があります。
atom(上記で説明されていない、その他のあらゆる種類の非リストを指す。) それに「等しい」あらゆるものにマッチする。
(rx regexp)関数 rx のように S-式形式で指定された正規表現(rx 構造化正規表現表記
を参照)を使用し、それによってデータにマッチさせます。
(rx regexp sym0 sym1…)
s式形式で指定された正規表現を使用し、シンボル sym0、sym1 などを (match-string 0 datum)、(match-string 1 datum)
などにバインドします。正規表現のマッチングがサポートする限り、任意の数の sym を使用できます。
`objectequal から object
までの任意の値に一致します。
(cons carpat cdrpat)carpat がその car に、cdrpat がその cdr にそれぞれマッチする場合、cons
セルにマッチする。
(list eltpats…)eltpats がリストの要素にマッチすれば、リストにマッチします。最初の eltpat はリストの最初の要素に、2番目の eltpat はリストの2番目の要素に、というようにマッチします。
(vector eltpats…)eltpats が要素にマッチすれば、ベクトルにマッチします。最初の eltpat はベクトルの第1要素に、2番目の eltpat はベクトルの第2要素に、というようにマッチします。
(cdr pattern)pattern にマッチし、cdr
を厳密にチェックします。つまり、list パターンは最後の cdr が nil
であることを検証します。厳密なチェックがデフォルトです。
(cdr-ignore pattern)pattern にマッチし、cdr
のチェックは緩やかに行われます。つまり、list パターンは最後の cdr を検証しません。
(and conjuncts…)各 conjuncts を同一のデータと照合します。すべて一致すれば、このパターンは成功します。いずれか一つの conjunct が失敗すると、このパターンは失敗し、以降の conjuncts は試行されません。
(or disjuncts…)各 disjuncts を同一のデータと照合します。いずれか一つの disjunct が成功すれば、このパターンは成功し、以降の disjuncts は試行されません。すべて失敗した場合、このパターンは失敗します。
(cond*-expander …)ここで car はシンボルであり、パターン内での扱い方を定義する cond*-expander
プロパティを持っています。プロパティの値は関数です。このようなパターンにマッチさせようとすると、その関数が1つの引数(該当するパターン。car を含む)とともに呼び出されます。関数は、代わりにマッチさせるべき同等のパターンを返す必要があります。
(predicate symbol)(predicate datum) が真であればデータに一致し、symbol
を datum にバインドする。
(predicate SYMBOL more-args…)
(predicate datum more-args…) が真であればデータに一致し、symbol を datum にバインドします。more-args… は、パターン内で先にバインドされたシンボルを参照できます。
(constrain symbol exp)フォーム exp が真の場合、データに一致します。exp は、パターン内で先に束縛されたシンボルを参照できます。