8

次のwhenマクロでは:

(defmacro when (condition &rest body)
  `(if ,condition (progn ,@body)))

なぜ「アット」@記号があるのですか?

4

3 に答える 3

17

quasiquoted セクションに計算値を挿入する場合、次の 2 つの演算子があります。

  • 「コンマ」演算子,
  • 「カンマスプライス」演算子,@

カンマ,は、準引用符で囲まれた sexpr に次の式の値を挿入します。代わりに、カンマ スプライスは次の式を必要とします。次はリストであり、準引用符で囲まれたリスト内でのみ使用できます。演算子が現れる位置の引用符付きリスト。

ちょっとした実験で違いを確認するのはとても簡単です

> (let ((x '(1 2 3 4))) `(this is an example ,x of expansion))
(THIS IS AN EXAMPLE (1 2 3 4) OF EXPANSION)

> (let ((x '(1 2 3 4))) `(this is an example ,@x of expansion))
(THIS IS AN EXAMPLE 1 2 3 4 OF EXPANSION)

ご覧のとおり、 を使用する,@と、リストの要素が展開内に直接配置されます。代わりに、展開に配置されたリストを取得しなければ。

,@リストにならない式を使用すると、置換が実行されるときにエラーになります。

* (defun f (x) `(here ,@x we go))
F
* (f '(1 2 3))
(HERE 1 2 3 WE GO)
* (f '99)

debugger invoked on a TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {10009F80D3}>:
  The value
    99
  is not of type
    LIST
  when binding SB-IMPL::X

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-IMPL::APPEND2 99 (WE GO)) [external]
0] 

リスト内で notを使用,@すると、準引用セクションが分析されるときにエラーになります。

* (defun g (x) `,@x)

debugger invoked on a SB-INT:SIMPLE-READER-ERROR in thread
#<THREAD "main thread" RUNNING {10009F80D3}>:
  `,@X is not a well-formed backquote expression

    Stream: #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDIN* {10000279E3}>

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-IMPL::BACKQUOTE-CHARMACRO #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDIN* {10000279E3}> #<unused argument>)
0] 
于 2011-04-14T10:36:58.763 に答える
0

そのマクロ定義は次と同等です

(defmacro when (condition &rest body) 
  (list 'if condition (cons 'progn body)))

しかし、なしでは@それは同等です

(defmacro when (condition &rest body) 
  (list 'if condition (list 'progn body)))

はリストであるためbody、括弧で囲まれた関数呼び出しのように評価されます。たとえば、次の(when t 1 2 3)ように展開されます。

(if t (progn (1 2 3)))

正しいのではなく

(if t (progn 1 2 3))
于 2020-12-12T16:20:20.733 に答える