add a little more about quasiquote to the guide
Please merge to the 5.1 release branch
This commit is contained in:
parent
8f404a4618
commit
74f8b0e2f1
|
@ -119,6 +119,22 @@ pattern variables can be bound to lists of lists of matches:
|
|||
[(list (list '! x ...) ...) x])
|
||||
]
|
||||
|
||||
|
||||
The @racket[quasiquote] form (see @secref["qq"] for more about it) can also be used to build patterns.
|
||||
While unquoted portions of a normal quasiquoted form mean regular racket evaluation, here unquoted
|
||||
portions mean go back to regular pattern matching.
|
||||
|
||||
So, in the example below, the with expression is the pattern and it gets rewritten into the
|
||||
application expression, using quasiquote as a pattern in the first instance and quasiquote
|
||||
to build an expression in the second.
|
||||
|
||||
@interaction[
|
||||
#:eval match-eval
|
||||
(match `{with {x 1} {+ x 1}}
|
||||
[`{with {,id ,rhs} ,body}
|
||||
`{{lambda {,id} ,body} ,rhs}])
|
||||
]
|
||||
|
||||
For information on many more pattern forms, see @racketmodname[racket/match].
|
||||
|
||||
Forms like @racket[match-let] and @racket[match-lambda] support
|
||||
|
|
|
@ -24,6 +24,63 @@ evaluated to produce a value that takes the place of the
|
|||
`(1 2 ,(+ 1 2), (- 5 1)))
|
||||
]
|
||||
|
||||
This form can be used to write functions that build lists according to
|
||||
certain patterns.
|
||||
|
||||
@examples[
|
||||
(eval:alts (define (deep n)
|
||||
(cond
|
||||
[(zero? n) 0]
|
||||
[else
|
||||
(#,qq ((#,uq n) (#,uq (deep (- n 1)))))]))
|
||||
(define (deep n)
|
||||
(cond
|
||||
[(zero? n) 0]
|
||||
[else
|
||||
(quasiquote ((unquote n) (unquote (deep (- n 1)))))])))
|
||||
(deep 8)
|
||||
]
|
||||
|
||||
Or even to cheaply construct expressions programmatically. (Of course, 9 times out of 10,
|
||||
you should be using a @seclink["macros"]{macro} to do this
|
||||
(the 10th time being when you're working through
|
||||
a textbook like @hyperlink["http://www.cs.brown.edu/~sk/Publications/Books/ProgLangs/"]{PLAI}).)
|
||||
|
||||
@examples[(define (build-exp n)
|
||||
(add-lets n (make-sum n)))
|
||||
|
||||
(eval:alts
|
||||
(define (add-lets n body)
|
||||
(cond
|
||||
[(zero? n) body]
|
||||
[else
|
||||
(#,qq
|
||||
(let ([(#,uq (n->var n)) (#,uq n)])
|
||||
(#,uq (add-lets (- n 1) body))))]))
|
||||
(define (add-lets n body)
|
||||
(cond
|
||||
[(zero? n) body]
|
||||
[else
|
||||
(quasiquote
|
||||
(let ([(unquote (n->var n)) (unquote n)])
|
||||
(unquote (add-lets (- n 1) body))))])))
|
||||
|
||||
(eval:alts
|
||||
(define (make-sum n)
|
||||
(cond
|
||||
[(= n 1) (n->var 1)]
|
||||
[else
|
||||
(#,qq (+ (#,uq (n->var n))
|
||||
(#,uq (make-sum (- n 1)))))]))
|
||||
(define (make-sum n)
|
||||
(cond
|
||||
[(= n 1) (n->var 1)]
|
||||
[else
|
||||
(quasiquote (+ (unquote (n->var n))
|
||||
(unquote (make-sum (- n 1)))))])))
|
||||
(define (n->var n) (string->symbol (format "x~a" n)))
|
||||
(build-exp 3)]
|
||||
|
||||
The @racket[unquote-splicing] form is similar to @racket[unquote], but
|
||||
its @racket[_expr] must produce a list, and the
|
||||
@racket[unquote-splicing] form must appear in a context that produces
|
||||
|
@ -35,6 +92,46 @@ is spliced into the context of its use.
|
|||
`(1 2 ,@(list (+ 1 2) (- 5 1)) 5))
|
||||
]
|
||||
|
||||
Using splicing we can revise the construction of our example expressions above
|
||||
to have just a single @racket[let] expression and a single @racket[+] expression.
|
||||
|
||||
@examples[(eval:alts
|
||||
(define (build-exp n)
|
||||
(add-lets
|
||||
n
|
||||
(#,qq (+ (#,(racket unquote-splicing)
|
||||
(build-list
|
||||
n
|
||||
(λ (x) (n->var (+ x 1)))))))))
|
||||
(define (build-exp n)
|
||||
(add-lets
|
||||
n
|
||||
(quasiquote (+ (unquote-splicing
|
||||
(build-list
|
||||
n
|
||||
(λ (x) (n->var (+ x 1))))))))))
|
||||
(eval:alts
|
||||
(define (add-lets n body)
|
||||
(#,qq
|
||||
(let (#,uq
|
||||
(build-list
|
||||
n
|
||||
(λ (n)
|
||||
(#,qq
|
||||
[(#,uq (n->var (+ n 1))) (#,uq (+ n 1))]))))
|
||||
(#,uq body))))
|
||||
(define (add-lets n body)
|
||||
(quasiquote
|
||||
(let (unquote
|
||||
(build-list
|
||||
n
|
||||
(λ (n)
|
||||
(quasiquote
|
||||
[(unquote (n->var (+ n 1))) (unquote (+ n 1))]))))
|
||||
(unquote body)))))
|
||||
(define (n->var n) (string->symbol (format "x~a" n)))
|
||||
(build-exp 3)]
|
||||
|
||||
If a @racket[quasiquote] form appears within an enclosing
|
||||
@racket[quasiquote] form, then the inner @racket[quasiquote]
|
||||
effectively cancels one layer of @racket[unquote] and
|
||||
|
|
Loading…
Reference in New Issue
Block a user