quasisyntax: recognize unsyntax
in a box
This is a backward-incompatible change, but I think it's unlikely that any code intentionally uses `unsyntax` or `unsyntax-splicing` within a syntax-quoted box and expects it to stay literal. Meanwhile, as @rocketnia noted, the documentation for `quasiquote` was unclear about the espacing positions for `unquote` and `unquote-splicing`, so this commit impoves that documentation. It adjusts the documentation for `quasisyntax` to note that a hash table value position is not an escape position, unlike for `quasiquote`. (The lack of an escape position within hash tables is consistent with `syntax`. That's arguably inconsistent with `quasiquote`, but it seems simpler to leave that alone, and changing `syntax` just might matter for existing code.) Closes #3656
This commit is contained in:
parent
c8d605a8cc
commit
fc955b99f3
|
@ -449,15 +449,16 @@ variables, then @racket[#'template] is equivalent to
|
|||
|
||||
@defform[(quasisyntax template)]{
|
||||
|
||||
Like @racket[syntax], but @racket[(#,(racketkeywordfont "unsyntax")
|
||||
_expr)] and @racket[(#,(racketkeywordfont "unsyntax-splicing") _expr)]
|
||||
Like @racket[syntax], but @racket[(@#,racket[unsyntax]
|
||||
_expr)] and @racket[(@#,racket[unsyntax-splicing] _expr)]
|
||||
escape to an expression within the @racket[template].
|
||||
|
||||
The @racket[_expr] must produce a syntax object (or syntax list) to be
|
||||
substituted in place of the @racket[unsyntax] or
|
||||
@racket[unsyntax-splicing] form within the quasiquoting template, just
|
||||
like @racket[unquote] and @racket[unquote-splicing] within
|
||||
@racket[quasiquote]. (If the escaped expression does not generate a
|
||||
@racket[quasiquote], except that a hash table value position is not
|
||||
an escape position for @racket[quasisyntax]. (If the escaped expression does not generate a
|
||||
syntax object, it is converted to one in the same way as for the
|
||||
right-hand side of @racket[with-syntax].) Nested
|
||||
@racket[quasisyntax]es introduce quasiquoting layers in the same way
|
||||
|
|
|
@ -2861,21 +2861,28 @@ The same as @racket[(quote datum)] if @racket[datum] does not include
|
|||
and the result of the @racket[_expr] takes the place of the
|
||||
@racket[(#,unquote-id _expr)] form in the @racket[quasiquote] result. An
|
||||
@racket[(#,unquote-splicing-id _expr)] similarly escapes, but the
|
||||
@racket[_expr] must produce a list, and its elements are spliced as
|
||||
multiple values place of the @racket[(#,unquote-splicing-id _expr)], which
|
||||
must appear as the @racket[car] of a quoted pair, as an element of a
|
||||
quoted vector, or as an element of a quoted @tech{prefab} structure;
|
||||
in the case of a pair, if the @racket[cdr] of the relevant quoted pair
|
||||
is empty, then @racket[_expr] need not produce a list, and its result
|
||||
is used directly in place of the quoted pair (in the same way that
|
||||
@racket[append] accepts a non-list final argument). In a quoted
|
||||
@tech{hash table}, an @racket[(#,unquote-id _expr)] or
|
||||
@racket[(#,unquote-splicing-id _expr)] expression escapes only in the
|
||||
second element of an entry pair (i.e., the value), while entry keys
|
||||
are always implicitly quoted. If @racket[unquote] or
|
||||
@racket[unquote-splicing] appears within @racket[quasiquote] in any
|
||||
other way than as @racket[(#,unquote-id _expr)] or
|
||||
@racket[(#,unquote-splicing-id _expr)], a syntax error is reported.
|
||||
@racket[_expr] produces a list whose elements are spliced as
|
||||
multiple values place of the @racket[(#,unquote-splicing-id _expr)].
|
||||
|
||||
An @|unquote-id| or @|unquote-splicing-id| form is recognized in any
|
||||
of the following escaping positions within @racket[datum]: in a pair,
|
||||
in a vector, in a box, in a @tech{prefab} structure field after the
|
||||
name position, and in hash table value position (but not in a hash
|
||||
table key position). Such escaping positions can be nested to an
|
||||
arbitrary depth.
|
||||
|
||||
An @|unquote-splicing-id| form must appear as the @racket[car] of a
|
||||
quoted pair, as an element of a quoted vector, or as an element of a
|
||||
quoted @tech{prefab} structure. In the case of a pair, if the
|
||||
@racket[cdr] of the relevant quoted pair is empty, then @racket[_expr]
|
||||
need not produce a list, and its result is used directly in place of
|
||||
the quoted pair (in the same way that @racket[append] accepts a
|
||||
non-list final argument).
|
||||
|
||||
If @racket[unquote] or @racket[unquote-splicing] appears within
|
||||
@racket[quasiquote] in an escaping position but in a way other than as
|
||||
@racket[(#,unquote-id _expr)] or @racket[(#,unquote-splicing-id
|
||||
_expr)], a syntax error is reported.
|
||||
|
||||
@mz-examples[
|
||||
(eval:alts (#,(racket quasiquote) (0 1 2)) `(0 1 2))
|
||||
|
|
|
@ -2353,6 +2353,7 @@
|
|||
(test '((1) (2)) syntax->datum (quasisyntax ((a) ((unsyntax b)))))
|
||||
(test '#(1 2) syntax->datum (quasisyntax #(a (unsyntax b))))
|
||||
(test '#(1 2 3 4 5) syntax->datum (quasisyntax #(a (unsyntax b) c ...)))
|
||||
(test '#&2 syntax->datum (quasisyntax #&(unsyntax b)))
|
||||
(test '#s(PS 1 2) syntax->datum (quasisyntax #s(PS a (unsyntax b))))
|
||||
(test '#s(PS 1 2 3 4 5) syntax->datum (quasisyntax #s(PS a (unsyntax b) c ...)))
|
||||
(test '#(1 2 3 4 5) syntax->datum (quasisyntax #(a (unsyntax b) (unsyntax-splicing ds))))
|
||||
|
@ -2368,6 +2369,7 @@
|
|||
(syntax-test #'(quasisyntax unsyntax-splicing))
|
||||
(syntax-test #'(quasisyntax (unsyntax-splicing)))
|
||||
(syntax-test #'(quasisyntax (unsyntax-splicing 1 2)))
|
||||
(syntax-test #'(quasisyntax #&(unsyntax-splicing 1 2)))
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Check preservation of properties by `quasisyntax'
|
||||
|
|
|
@ -250,6 +250,17 @@
|
|||
stx
|
||||
stx)
|
||||
bindings))))]
|
||||
[(box? (syntax-e stx))
|
||||
(loop (unbox (syntax-e stx))
|
||||
depth
|
||||
same-k
|
||||
(lambda (v bindings)
|
||||
(convert-k (datum->syntax
|
||||
stx
|
||||
(box v)
|
||||
stx
|
||||
stx)
|
||||
bindings)))]
|
||||
[(prefab-struct-key (syntax-e stx))
|
||||
(let* ([d (syntax-e stx)]
|
||||
[key (prefab-struct-key d)]
|
||||
|
|
Loading…
Reference in New Issue
Block a user