R6RS:翻訳:R6RS:11.17 Quasiquotation

R6RS:翻訳:R6RS:11.17 Quasiquotation

11.17 準引用

[syntax] (quasiquote <qq template>)

[auxiliary syntax] unquote

[auxiliary syntax] unquote-splicing

「逆引用符」ないしは「準引用符」式は所望の構造が前以って全体ではなくいくらかわかっている場合に便利な構文である。

構文: <qq template> はこの項目の最後に挙げてある構文に指定されているようになっている。

意味論: unquote や unquote-splicing フォームが <qq- template> の中に現れない場合、 (quasiquote <qq template>) の評価結果は (quote <qq template>) の評価結果と等価である。

(unquote <expression> ...) が <qq template> の中に現れた場合、 <expression> は評価され(「引用を外され」)その評価結果が unquote フォームの代わりに構造に差し込まれる。

(unquote-splicing <expression> ...) フォームが <qq template> の内部に現れた場合、 <expression> はリストに評価されなければならない。リストの開き括弧と閉じ括弧が「剥ぎ取られ」リストの要素が unquote-splicing フォームのあった場所に挿入される。

どの unquote-splicing も多引き数の unquote フォームもリストやベクタの <qq template> の中に現れなければならない。

4.3.5 で触れた通り、 (quasiquote <qq template> は `<qq template> と、 (unquote <expression>) は ,<expression> と、 (unquote-splicing <expression>) は ,@<expression> と略記することができる。

‘(list ,(+ 1 2) 4)          ⇒  (list 3 4)
(let ((name ’a)) ‘(list ,name ’,name)) 
                ⇒  (list a (quote a))
‘(a ,(+ 1 2) ,@(map abs ’(4 -5 6)) b) 
                ⇒  (a 3 4 5 6 b)
‘(( foo ,(- 10 3)) ,@(cdr ’(c)) . ,(car ’(cons))) 
                ⇒  ((foo 7) . cons)
‘#(10 5 ,(sqrt 4) ,@(map sqrt ’(16 9)) 8) 
                ⇒  #(10 5 2 4 3 8)
(let ((name ’foo))
  ‘((unquote name name name)))
                ⇒ (foo foo foo)
(let ((name ’(foo)))
  ‘((unquote-splicing name name name)))
                ⇒ (foo foo foo)
(let ((q ’((append x y) (sqrt 9))))
  ‘‘(foo ,,@q)) 
                ⇒ ‘(foo
                 (unquote (append x y) (sqrt 9)))
(let ((x ’(2 3))
      (y ’(4 5)))
  ‘(foo (unquote (append x y) (sqrt 9)))) 
                ⇒ (foo (2 3 4 5) 3)

quasiquote フォームは入れ子にすることができる。置き換えは一番外側の quasiquote と同じ入れ子レベルの部分に現れた unquote された要素にだけ行われる。入れ子レベルはそれぞれ次の quasiquote で 1 増加し、 unquote の内側で 1 減少する。

‘(a ‘(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f) 
                ⇒  (a ‘(b ,(+ 1 2) ,(foo 4 d) e) f)
(let ((name1 ’x)
      (name2 ’y))
  ‘(a ‘(b ,,name1 ,’,name2 d) e)) 
                ⇒  (a ‘(b ,x ,’y d) e)

quasiquote 式は新たな変更可能なオブジェクトも、実行時の式の評価中に構築される任意の構造のリテラル構造を返すこともある。再構築する必要のない部分は常にリテラルになる。したがって、

(let ((a 3)) ‘((1 2) ,a ,4 ,’five 6))

は次の式のどちらかと等価である可能性がある。

’((1 2) 3 4 five 6)
(let ((a 3)) 
  (cons ’(1 2)
        (cons a (cons 4 (cons ’five ’(6))))))

ただし、この式とは等価ではない。

(let ((a 3)) (list (list 1 2) a 4 ’five 6))

識別子 quasiquote、 unquote、 unquote-splicing いずれかが上で述べた以外の <qq template> の部分に現れた場合は構文違反である。

次の quasiquote 式の文法は文脈自由ではない。無限個の生成規則を生成するための規則として与えられている。以下の規則を D = 1, 2, 3, ... について複製したものを想像してみよ。 D は入れ子の深さを追跡する数である。

 <qq template> → <qq template 1>
 <qq template 0> → <expression>
 <quasiquotation D> → (quasiquote <qq template D>)
 <qq template D> → <lexeme datum>
          | <list qq template D>
          | <vector qq template D>
          | <unquotation D>
 <list qq template D> → (<qq template or splice D>*)
          | (<qq template or splice D>+ . <qq template D>)
          | <quasiquotation D + 1>
 <vector qq template D> → #(<qq template or splice D>*)
 <unquotation D> → (unquote <qq template D - 1>)
 <qq template or splice D> → <qq template D>
          | <splicing unquotation D>
 <splicing unquotation D> →
             (unquote-splicing <qq template D - 1>*)
          | (unquote <qq template D - 1>*)

<quasiquotation> 中では、 <list qq template D> が <unquotation D> か <splicing unquotation D> のどちらかまぎらわしいことがあるが、このときは <unquotation> や <splicing unquotation D> としての解釈の方が優先される。


Last modified : 2008/04/03 09:05:28 UTC