
Started as fixing misindented definitions, then more indentations, then a bunch of similar things (square brackets, huge spaces at end-of-lines, etc).
40 lines
1.4 KiB
Racket
40 lines
1.4 KiB
Racket
#lang scribble/doc
|
|
@(require scribble/manual
|
|
scribble/struct
|
|
scribble/decode
|
|
scribble/eval
|
|
"parse-common.rkt"
|
|
(for-label racket/class))
|
|
|
|
@title[#:tag "exprc"]{Contracts on Macro Sub-expressions}
|
|
|
|
Just as procedures often expect certain kinds of values as arguments,
|
|
macros often have expectations about the expressions they are
|
|
given. And just as procedures express those expectations via
|
|
contracts, so can macros, using the @racket[expr/c] syntax class.
|
|
|
|
For example, here is a macro @racket[myparameterize] that behaves like
|
|
@racket[parameterize] but enforces the @racket[parameter?] contract on
|
|
the parameter expressions.
|
|
|
|
@myinteraction[
|
|
(define-syntax (myparameterize stx)
|
|
(syntax-parse stx
|
|
[(_ ((p v:expr) ...) body:expr)
|
|
#:declare p (expr/c #'parameter?
|
|
#:name "parameter argument")
|
|
#'(parameterize ([p.c v] ...) body)]))
|
|
(myparameterize ([current-input-port
|
|
(open-input-string "(1 2 3)")])
|
|
(read))
|
|
(myparameterize (['whoops 'something])
|
|
'whatever)
|
|
]
|
|
|
|
@bold{Important:} Make sure when using @racket[expr/c] to use the
|
|
@racket[c] attribute. If the macro above had used @racket[p] in the
|
|
template, the expansion would have used the raw, unchecked
|
|
expressions. The @racket[expr/c] syntax class does not change how
|
|
pattern variables are bound; it only computes an attribute that
|
|
represents the checked expression.
|