Go to the first, previous, next, last section, table of contents.

バッククォート

関数 list を呼ぶ回数だけを考えても、あまり大きなマクロを書くのは、うまくありま せん。前に記した for の例は(妥当な)リストの深さの(ほぼ)限界を示しています。 (このような)フォームを書くのをたやすくするため、マクロ ` (バッククォートと呼 ぶ)が与えられています。

バッククォートはリストをクォートしますが、リストの要素を選択的に評価します。こ れは(その一番単純なフォームにおいて)特殊フォーム quote と同じ働きをします。以 下に示す 2つのフォームは、同じ結果になります。

      (` (a list of (+ 2 3) elements))
      => (a list of (+ 2 3) elements)
      (quote (a list of (+ 2 3) elements))
      => (a list of (+ 2 3) elements)

バッククォートに対するアーギュメント中に特別なマーカー (,) を入れることで、 アーギュメントの(評価させたい)部分のみを評価させることができます。

      (list 'a 'list 'of (+ 2 3) 'elements)
      => (a list of 5 elements)
      (` (a list of (, (+ 2 3)) elements))
      => (a list of 5 elements)

特別なマーカー (,@) を用いることで、リストを評価し(要素にするのではなく) 結果 のリストに組み込む(訳注:splice in)こともできます。

      (cons 1 (list (+ 1 1) (+ 1 2)))
      => (1 2 3)
      (` (1 (,@ (list (+ 1 1) (+ 1 2)))))
      => (1 2 3)
      ;; もっとひどい例
      (cons 'a
        (cons 'list
          (cons 'of (append (list (+ 2 3)) '(elements)))))
      => (a list of 5 elements)
      (` (a list of (,@ (list (+ 2 3))) elements))
      => (a list of 5 (elements))   ?????
      => (a list of 5 elements)

これにより、for マクロは (より明確に)次のように書き直すことができます。

      (defmacro for (var from init to final fo &rest body)
        "Execute a simple for loop: (for i from 1 to 10 do (print i))."
        (` (let (( (, var) (, init) ))
             (while (<= (, var) (, final))
                    (,@ body)
                    (inc (, var))
                    ))))
      => for

Macro: ` list

このマクロは、quote が行なうように list を返します。違いは、特別なマーカー (,) で始まるサブリストはその 2番目の要素を評価し、特別なマーカー (,@) で始 まるサブリストはその 2番目の要素を評価しその結果を新しく作られるリストに組 み込む点です。

このような特別なマークを付けられたサブリストが 2つ以上の要素を持つ場合、そ の要素は無視されることになります。

??避けられなくてはいけない微妙なバグがいくつかあります。以下のフォームは期 待するようには動きません。

  (` (a . (, 1)))
  => (a \, 1)                    ; (a . 1) でない
  (` [a (, 1) c])
  -> ERROR: Wrong type argument   ; [a 1 c] でない
  (` (, 2))
  => (\, 2)                      ; 2 でない


Go to the first, previous, next, last section, table of contents.