20

私は Let Over Lambda を読んでいます。これは、かなり深く階層化されたマクロ オーサリングを扱っています。それは魅力的で、私はほとんどそれについていくことができています.

第 4 章では、Hoyte が CL-PPCRE の一致および置換関数用のリーダー マクロを実装しており、次のようなことができます。

(#~m/(foo|bar)\d+/ "Some foo99")    ; matches!
(#~s/foo(\d+)/bar\1/, "Some foo99") ; "Some bar99

これを実現するために、二重バッククォートを使用するマクロを定義します。実際には、引用符で囲まれた値を必要とするラッパー マクロによって展開されるためです (ラムダ形式を返します)。準引用リスト内で、次のシーケンスが使用されていますが,',varname、これについては理解できません。ここでイニシャルは何をし,'ますか?

(defmacro! pcre/match-lambda-form (o!args)
  "Expands to a lambda that applies CL-PPCRE:SCAN"
  ``(lambda (,',g!str)
      (cl-ppcre:scan ,(car ,g!args)
                     ,',g!str)))

defmacro実際には、本を読んでいない場合にわかりやすくするために、単に を使用するものにそれを抽出した方がよいでしょう。strはシンボルでargsあり、リストです:

(defmacro pcre/match-lambda-form (args)
  "Expands to a lambda that applies CL-PPCRE:SCAN"
  ``(lambda (,',str)
      (cl-ppcre:scan ,(car ,args)
                     ,',str)))

引用符は基本的に内側の部分を二重引用符で囲んでいるので、結果を 2 回引用符で外すことができますか? 'str単にstr?ではなく、展開された形式に効果的に入れる。

編集 | Terje D.とREPLで遊んでいる人たちのおかげで、これはほとんど状況です:

(defvar a 42)

(equal ``(,,a)  '(list 42)) ; T
(equal ``(,a)   '(list a))  ; T
(equal ``(,',a) ''(42))     ; T
(equal ``(a)    ''(a))      ; T (obviously)

そう:

  • 二重引用符なし、フォームは完全に展開されています。
  • 単独引用符なし、フォームは展開されません。
  • コンマで引用されていない場合、フォームは完全に展開され、結果が引用されます。
4

2 に答える 2

13

二重にバッククォートされたフォームの評価中、内側のバッククォートが最初に処理され、結果は単一にバッククォートされたフォームになります。内側のバッククォート形式の評価では、2 つのコンマが前にある要素のみが評価されます。ただし、これらの二重引用符で囲まれていない要素を評価した結果は、まだ (単一で) 引用符で囲まれていないため、結果として単一で逆引用符で囲まれた形式が評価されるときに、再度評価されます。内側の逆引用符で囲まれた形式でのみ評価を行うには、通常の引用符を挿入する必要があり、,',.

方法を見る

(let ((tmp (gensym)))
    ``(lambda (,tmp ,,tmp ,',tmp) ()))

に評価されます

`(LAMBDA (,TMP ,#:G42 #:G42) nil)
于 2013-07-03T09:09:16.610 に答える
3

,',X トリックは、X を別の評価から保護するために使用されます。

方法を見る:

     (setq a 'fn)
     (let ((x 'a)) ``(,,x ,',x)) ==>  `(,a a) ==> (fn a)

     ;; ``,',X ==> `,(quote "the value of X") ==> "the value of X"

     ;; ``,,X  ==> `,"the value of X" ==> "the value of the value of X"
于 2013-12-02T14:18:50.340 に答える