# Lisp Quote 和Backquote分析

• 引用 （quote）

Quote 的等价形式是‘ ，‘是Quote的语法糖。两个形式是完全等价了。读取器将’翻译为quote的等价形式。

'(value-of-number (1+ number) something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER (1+ NUMBER) SOMETHING-WITH-STRING (LENGTH STRING))

(defun mess-with (number string)
(list 'value-of-number (1+ number) 'something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER 21 SOMETHING-WITH-STRING 3)

(defun mess-with (number string )
(value-of-string ,(+ 1 number ) something-with-string ,(length string )) )

Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL

Lisp> 'spiffy-symbol ; '是quote的等价形式，和上一个表达式相同
SPIFFY-SYMBOL

Lisp> spiffy-symbol
Unbound variable: SPIFFY-SYMBOL
[Condition of type UNBOUND-VARIABLE]

Restarts:
0: [CONTINUE] Retry getting the value of SPIFFY-SYMBOL.
Unbound variable: SPIFFY-SYMBOL
[Condition of type UNBOUND-VARIABLE]

Restarts:
0: [CONTINUE] Retry getting the value of SPIFFY-SYMBOL.

进深阅读：Ron Garret's The Idiot's Guide to Common Lisp Packages

• 反引用（backquote）

## ,x ‘(a ,,b c) ‘(a ,(b ,c) d) ‘(,,‘a)

• 嵌套的反引用（nested backquote）

“为了定义一个定义宏的宏，我们通常会要用到嵌套的反引用。嵌套反引用的难以理解是出了名的。尽管最

stackoverflow有一个问答对Lisp的嵌套反引用解释的很透彻，我们下面来分析一下：

CLTS2里面说：

R5RS Scheme语言规范关于反引号这么定义：

(a ,,(+ 1 2) ,(+ 3 4))

(A ,3 ,(+ 3 4))

2，另一个表达式，（+ 3 4）因为没有足够的逗号所以未求值。
3，只有一个反引用被展开，因为反引用不会递归的展开。

(eval (a ,,(+ 1 2) ,(+ 3 4)))

(A 3 7)
解析： 其实就是对第一次求值的结果继续求值，就可以得到上面的结果。

<<On Lisp>>一书上说，反引用的嵌套一般发生在定义宏的宏上面。下面是书中的一个例子：定义一个宏的简称的的宏。

（defmacro dbind (&rest args)
(destructruing-bind ,@args))
（defmacro mvbind (&rest args)
(multiple-value-bind ,@args))

(defmacro abbrev (short long)
(defmacro ,short (&rest args)
(,',long ,@args)))

（defmacro mvbind (&rest args)
(multiple-value-bind ,@args))

（defmacro mvbind (&rest args)
(let ( (name 'multiple-value-bind ))
(,name ,@args) ) )

(defmacro ,short (& rest args)
(let (( name ',long ))
(,name ,@args) ) )

(defmacro ,short (&rest args)
(,',long ,@args) ) )

(DEFMACRO ,SHORT (&REST ARGS) (LIST* ',LONG ARGS))

## Backquote

The backquote introduces a template of a data structure to be built. For example, writing

(cond ((numberp ,x) ,@y) (t (print ,x) ,@y))
is roughly equivalent to writing
(list 'cond
(cons (list 'numberp x) y)
(list* 't (list 'print x) y))
Where a comma occurs in the template, the expression following the comma is to be evaluated to produce an object to be inserted at that point. Assume b has the value 3, for example, then evaluating the form denoted by (a b ,b ,(+ b 1) b) produces the result (a b 3 4 b).

If a comma is immediately followed by an at-sign, then the form following the at-sign is evaluated to produce a list of objects. These objects are then spliced'' into place in the template. For example, if x has the value (a b c), then

(x ,x ,@x foo ,(cadr x) bar ,(cdr x) baz ,@(cdr x))
=>  (x (a b c) a b c foo b bar (b c) baz b c)
The backquote syntax can be summarized formally as follows.
* basic is the same as 'basic, that is, (quote basic), for any expression basic that is not a list or a general vector.

* ,form is the same as form, for any form, provided that the representation of form does not begin with at-sign or dot. (A similar caveat holds for all occurrences of a form after a comma.)

* ,@form has undefined consequences.

* (x1 x2 x3 ... xn . atom) may be interpreted to mean

(append [ x1] [ x2] [ x3] ... [ xn] (quote atom))
where the brackets are used to indicate a transformation of an xj as follows:
-- [form] is interpreted as (list form), which contains a backquoted form that must then be further interpreted.

-- [,form] is interpreted as (list form).

-- [,@form] is interpreted as form.

* (x1 x2 x3 ... xn) may be interpreted to mean the same as the backquoted form (x1 x2 x3 ... xn . nil), thereby reducing it to the previous case.

* (x1 x2 x3 ... xn . ,form) may be interpreted to mean

(append [ x1] [ x2] [ x3] ... [ xn] form)
where the brackets indicate a transformation of an xj as described above.
* (x1 x2 x3 ... xn . ,@form) has undefined consequences.

* #(x1 x2 x3 ... xn) may be interpreted to mean (apply #'vector (x1 x2 x3 ... xn)).

Anywhere ,@'' may be used, the syntax ,.'' may be used instead to indicate that it is permissible to operate destructively on the list structure produced by the form following the ,.'' (in effect, to use nconc instead of append).

If the backquote syntax is nested, the innermost backquoted form should be expanded first. This means that if several commas occur in a row, the leftmost one belongs to the innermost backquote.

An implementation is free to interpret a backquoted form F1 as any form F2 that, when evaluated, will produce a result that is the same under equal as the result implied by the above definition, provided that the side-effect behavior of the substitute form F2 is also consistent with the description given above. The constructed copy of the template might or might not share list structure with the template itself. As an example, the above definition implies that

((,a b) ,c ,@d)
will be interpreted as if it were
(append (list (append (list a) (list 'b) 'nil)) (list c) d 'nil)
but it could also be legitimately interpreted to mean any of the following:
(append (list (append (list a) (list 'b))) (list c) d)
(append (list (append (list a) '(b))) (list c) d)
(list* (cons a '(b)) c d)
(list* (cons a (list 'b)) c d)
(append (list (cons a '(b))) (list c) d)
(list* (cons a '(b)) c (copy-list d))
Nested Backquote

This is what the Common Lisp HyperSpec says about nested backticks:

If the backquote syntax is nested, the innermost backquoted form should be expanded first. This means that if several commas occur in a row, the leftmost one belongs to the innermost backquote.

The R5RS Scheme spec also includes these details about backticks:

Quasiquote forms may be nested. Substitutions are made only for unquoted components appearing at the same nesting level as the outermost backquote. The nesting level increases by one inside each successive quasiquotation, and decreases by one inside each unquotation.

Also keep in mind that only one backtick gets collapsed per evaluation, just like a regular quote, it's not recursive.

### Rules in action

To see how these three details interact, let's expand your example a bit. This expression...

(a ,,(+ 1 2) ,(+ 3 4))

Gets evaluated to this (in SBCL notation):

(A ,3 ,(+ 3 4))
1. The left backtick got collapsed, so it the (+ 1 2) got escaped by the matching comma (the 2nd comma, according to the HyperSpec).
2. On the other hand, the (+ 3 4) didn't have enough commas to get expanded (which is what R5RS mentions).
3. Only one backtick got collapsed, because backticks don't get recursively expanded.

### Expanding both commas

To get rid of the other backtick, another level of evaluation is needed:

(eval `(a ,,(+ 1 2) ,(+ 3 4)))

Both backticks are gone, and we're left with a plain list:

(A 3 7)

http://stackoverflow.com/questions/7549550/using-two-backquotes-and-commas-common-lisp

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120