GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote-Patterns.html ・ emacs-doc.conao3.com

11.4.3 バッククォート形式のパターン

本節では、構造的なマッチングを容易にする組み込みパターンの集合であるバッククォート形式のパターンについて説明します。背景については、パターンマッチングの条件式を参照してください。

Backquoteスタイルのパターンは、pcaseパターン拡張(pcase-defmacroを用いて作成)の強力なセットであり、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 がコンスセルであり、かつその car が qpat1 に、cdr が qpat2 にそれぞれ一致する場合にマッチします。これは (qpat1 qpat2 …) のようにリストへも容易に一般化できます。

[qpat1 qpat2 … qpatm]

expval が長さ m のベクトルであり、その 0..(m-1) 番目の要素がそれぞれ qpat1、qpat2 … qpatm と一致する場合にマッチします。

symbol
keyword
number
string

expval の対応する要素が指定されたリテラルオブジェクト equal と一致する場合にマッチします。

,pattern

expval の対応する要素が pattern に一致する場合にマッチします。なお、pattern は pcase がサポートする任意の種類となります。(上記の例では、second-elem は symbol コアパターンであるため、あらゆるものにマッチし、second-elem を let-bind します。)

対応要素とは、backquote-style パターンにおいて、qpat の構造的位置と同じ構造的位置にある expval の部分のことです。(上記の例では、second-elem の対応要素は expval の2番目の要素となります。)

以下に、pcase を用いて簡単な式言語のインタプリタを実装する例を示します(なお、fn 節内のラムダ式が body と arg を適切にキャプチャするには、字句束縛が必要です(字句束縛 を参照)):

(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))))

最初の3つの節では、バッククォート形式のパターンが使用されています。`(add ,x ,y)は、formがリテラルシンボルaddで始まる3要素のリストであることを確認し、2番目と3番目の要素を抽出してそれぞれシンボルxとyにバインドするパターンです。これは分解として知られており、pcaseパターンによる分解を参照してください。節の本体ではxとyを評価し、その結果を加算します。同様に、call節は関数呼び出しを、fn節は無名関数の定義を実装しています。

残りの節ではコアパターンが使用されています。(pred numberp)は、formが数値である場合にマッチします。マッチすると、本体がそれを評価します。(pred symbolp)は、formがシンボルである場合にマッチします。マッチすると、本体はenvからそのシンボルを検索し、その関連付けを返します。最後に、_は何でもマッチするキャッチオールパターンであるため、構文エラーの報告に適しています。

この小さな言語によるサンプルプログラムと、その評価結果をいくつか挙げます:

(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