2011/07/10
Quasiquoting
As of 0.9.1 Gauche doesn't handle quasiquote patterns something like this:
gosh> ``(,,@(list 1 2)) `(,,@(list 1 2))
It may be arguable a bug, or an unspecified behavior in R5RS.
The outer-level quasiquote should expand unquote-splicing,
and that should produce (unquote 1 2)
; however, quasiquote
syntax in R5RS does not allow such pattern, so the resulting
form wouldn't be a valid quasiquotation. It doesn't explain
the above result, but if it's an error in R5RS term,
anything can happen.
(In fact, the result wasn't intended at all;
it was just an outcome of failing recognition of the pattern.)
Still, it is allowed to have (unquote 1 2)
as a pure datum,
it may be more reasonable that ``(,,@(list 1 2))
expands into `((unquote 1 2))
.
R6RS solved this ambiguity by allowing unquote
to have
multiple arguments. Since it is upper compatible to R5RS,
I decided to implement R6RS behavior in Gauche. Now you get this:
gosh> ``(,,@(list 1 2)) `((unquote 1 2))
And this:
gosh> `((unquote 1 2)) (1 2)
★ ★ ★
While thinking about this, I found a difference between Scheme and CL about quasiquoting that I was not aware before.
In Scheme, `a
, ,a
, ,@a
are merely a reader-level
abbreviation
of (quasiquote a)
, (unquote a)
and (unquote-splicing a)
,
respectively. The real semantics of quasiquoting is defined in terms
of the latter S-expressions.
In CL, quasiquoting (bakcquotes) are defined in reader level.
That is, comma-datum doesn't need to be an abbreviation of something
like (unquote datum)
or (comma datum)
. It doesn't
need to have list equivalents at all. The comma and comma-atmark
can be directly parsed by the reader, and transformed
to whatever piece of code that produces the desired result.
It is not obvious in a simple case, but see the followings:
In Allegro:
cl-user> `'`(,,(cons 1 (cons 2 nil))) '(excl::bq-list (1 2))
In CLisp:
[6]> `'`(,,(cons 1 (cons 2 nil))) '(LIST (1 2))
This means the inner backquote form are interpreted rather liberally.
On the other hand, I believe in Scheme this is the only
possible result (modulo printing `a
or (quasiquote a)
etc.)
gosh> `'`(,,(cons 1 (cons 2 '()))) '`(,(1 2))
A practical outcome of this difference is that, in CL, you cannot write an S-expression with a comma without corresponding backquote.
In Scheme, you can write a macro that implicitly inserts quasiquote:
gosh> (define-syntax implicit-qq (syntax-rules () [(_ x) (quasiquote x)])) #<undef> gosh> (implicit-qq ,(+ 1 2)) 3
IIUC, you can't do this in standard CL,
since the expression (implicit-qq ,(+ 1 2))
raises
error at the reader, before the form gets passed to the macro
expander.
Tags: quasiquote, r5rs, r6rs, CommonLisp
Dan M (2011/07/14 19:37:48):
shiro (2011/07/14 20:26:55):
Kaz Kylheku (2011/10/29 01:58:25):
shiro (2011/10/29 11:20:02):
Bill Schottstaedt (2012/05/31 22:24:54):
shiro (2012/06/01 04:07:49):