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])
|
[(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].
|
For information on many more pattern forms, see @racketmodname[racket/match].
|
||||||
|
|
||||||
Forms like @racket[match-let] and @racket[match-lambda] support
|
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)))
|
`(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
|
The @racket[unquote-splicing] form is similar to @racket[unquote], but
|
||||||
its @racket[_expr] must produce a list, and the
|
its @racket[_expr] must produce a list, and the
|
||||||
@racket[unquote-splicing] form must appear in a context that produces
|
@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))
|
`(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
|
If a @racket[quasiquote] form appears within an enclosing
|
||||||
@racket[quasiquote] form, then the inner @racket[quasiquote]
|
@racket[quasiquote] form, then the inner @racket[quasiquote]
|
||||||
effectively cancels one layer of @racket[unquote] and
|
effectively cancels one layer of @racket[unquote] and
|
||||||
|
|
Loading…
Reference in New Issue
Block a user