comma-comma-at in Common Lisp

2020-07-18 08:06发布

问题:

I am confused about how comma-comma-at does what it does.

An example of use of comma-comma-at is in Is there a use for double unquote (double comma) when defining a Lisp macro?

It seems to me that

(let ((parms '(x y)))
  ``(beg ,,@parms end))

expands to or something equivalent to

`(beg ,x ,y end)

How does it expands to that?

I was thinking, if I evaluate the double backquote form, it causes the second comma to do its work, and the result is:

`(beg ,<splice stuff here> end)

and it looks like Lisp interpreter should complain and say "I don't know what it means to splice stuff before a comma" in the sense that when Lisp encounters

`,@abc

it would be likely to say "I don't know what it means to splice stuff before a backquote. Don't ever do that again."

But somehow, the interpreter does not complain and simply choose to do

`(beg <splice stuff here and write comma in front of each of them> end)

Is that compatible with rules in CLHS backquote?


For readers information, comments following the answer refer to an old version of the answer, and lead to update of the answer. New readers don't need to read the comments.


Also see CHLS "innermost backquoted form should be expanded first" meaning

回答1:

CLHS states: "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."

So, the first comma unquotes the second backquote; the ,@ then splices in the contents of parms, as all quotes have been undone. Unquoting does not "replace" forms in steps as you describe - the commas just back up in the structure of backquoted forms when deciding how to evaluate the contained forms.

(let ((parms '(x y)))
  `(list 'beg ,@parms 'end))

obviously evaluates to (list 'beg x y 'end), which is what you are after here; producing a form that creates the desired structure as its output. The additional outer backquote is simply a shorthand for this syntax, in the same manner as '(foo bar) is (equality issues aside) a shorthand for (list 'foo 'bar).