Next: , Previous: , Up: パターンマッチングによる条件   [Contents][Index]


11.4.3 バッククォートスタイルパターン

このサブセクションでは構造化マッチングを容易にするビルトインパターンであるバッククォートスタイルパターン(backquote-style patterns)について説明します。背景についてはパターンマッチングによる条件を参照してください。

バッククォートスタイルパターンは(pcase-defmacroを使用して作成された)強力なpcaseパターン拡張であり、その構造(structure)の仕様にたいするexpvalのマッチを容易にします。

たとえば1つ目の要素が特定の文字列、2つ目の要素が任意の値であるような2要素リストのexpvalにたいするマッチはコアパターンを使用して記述できます:

(and (pred listp)
     ls
     (guard (= 2 (length ls)))
     (guard (string= "first" (car ls)))
     (let second-elem (cadr ls)))

しかし等価なバッククォートスタイルパターンで記述することもできます:

`("first" ,second-elem)

バッククォートスタイルパターンはより簡潔かつexpvalの構造と似ており、lsのバインドを要しません。

バッククォートスタイルパターンは`qpatのような形式をもちます。ここでqpatは以下の形式をもつことができます:

(qpat1 . qpat2)

expvalが( carqpat1cdrqpat2にマッチする)コンスセルならマッチ。(qpat1 qpat2 …)のように容易に一般化できる。

[qpat1 qpat2qpatm]

expvalが長さmの(0から(m-1)番目の要素がqpat1qpat2、…、qpatmにマッチする)ベクターならマッチ。

symbol
keyword
number
string

expvalの対応する要素が指定されたリテラルオブジェクトとequalならマッチ。

,pattern

expvalの対応する要素がpatternにマッチすればマッチ。patternpcaseがサポートするすべての種類のパターンであることに注意(上記の例ではsecond-elemsymbolコアパターンであり、これはすべてにマッチしてsecond-elemをletでバインドする)。

対応する要素(corresponding element)とはバッククォートスタイルパターンqpatにたいする構造的な位置に等しいようなexpvalの構造的な位置部分のことです(上記の例ではsecond-elemの対応する要素はexpvalの2つ目の要素)。

以下は小さな式言語用の単純なインタープリターの実装用にpcaseを使用する例です(bodyargを正しくキャプチャーするにはfnのclause内でlambda式にレキシカルバインディングが必要なことに注意):

(defun evaluate (form env)
  (pcase form
    (`(add ,x ,y)       (+ (evaluate x env)
                           (evaluate y env)))
    (`(call ,fun ,arg)  (funcall (evaluate fun env)
                                 (evaluate arg env)))
    (`(fn ,arg ,body)   (lambda (val)
                          (evaluate body (cons (cons arg val)
                                               env))))
    ((pred numberp)     form)
    ((pred symbolp)     (cdr (assq form env)))
    (_                  (error "Syntax error: %S" form))))

The first three clauses use backquote-style patterns. `(add ,x ,y) is a pattern that checks that form is a three-element list starting with the literal symbol add, then extracts the second and third elements and binds them to symbols x and y, respectively. This is known as destructuring, see pcaseパターンによる分解. The clause body evaluates x and y and adds the results. Similarly, the call clause implements a function call, and the fn clause implements an anonymous function definition.

残りのclauseではコアパターンが使用されています。(pred numberp)formが数値ならマッチします。マッチした場合にはbodyがそれを評価します。(pred symbolp)formがシンボルならマッチします。マッチした場合にはbodyはenv内のシンボルを照合して、それの連想値をリターンします。最後の_はすべてにマッチするcatch-allパターンなので、構文エラーの報告に適しています。

以下は評価した結果を含む、この小さな言語のサンプルプログラムの例です:

(evaluate '(add 1 2) nil)                 ⇒ 3
(evaluate '(add x y) '((x . 1) (y . 2)))  ⇒ 3
(evaluate '(call (fn x (add 1 x)) 2) nil) ⇒ 3
(evaluate '(sub 1 2) nil)                 ⇒ error

Next: pcaseパターンによる分解, Previous: pcaseの拡張, Up: パターンマッチングによる条件   [Contents][Index]

This page has generated for branch:master, commit:762705fb24fd90db318f2e51c1e762452d26f7e2 to check Japanese translation.