Reputation: 3887
I'm tring to define syntax class matching a parameter which is procedure.
I know how to match identifiers, expressions, another syntax classes.
This is my sample:
(define-syntax-class model-property
#:description "a model property"
#:attributes (name datatype guard)
(pattern name:id
#:with datatype #`null
#:with guard #'(lambda (value) value)
)
(pattern [name:id #:datatype [datatype:id #:not-null] #:guard guard:expr])
)
And I'd like to replace #:guard guard:expr
with something like #:guard guard:procedure
I experimented with
(define-syntax-class model-property-guard
#:description "a property guard"
(pattern guard:expr
#:fail-when (procedure? #'guard)
"property guard should be procedure."))
Is it possible? How?
Upvotes: 3
Views: 256
Reputation: 43902
Macros run at compile-time, before the program is executed. You can’t, at compile-time, know what sort of value an expression will produce—the information simply doesn’t exist. (You could theoretically check such a thing in a language with a static type system, but #lang racket
is dynamically typed.)
One thing you can do is put a contract on an expression so that it raises a runtime error if the contract isn’t matched. The expr/c
syntax class is provided for this purpose. You use it like this:
(begin-for-syntax
(define-syntax-class model-property-guard
#:description "a property guard"
(pattern (~var guard (expr/c #'procedure?))
#:with c #'guard.c)))
(define-syntax (m stx)
(syntax-parse stx
[(_ guard:model-property-guard)
#'guard.c]))
Using the above definitions, writing (m add1)
will successfully produce #<procedure:add1>
, while writing (m 1)
will fail at runtime with a contract violation:
m: contract violation
expected: procedure?
given: 1
in: procedure?
Note that the expansion must use guard.c
in the expansion! The c
attribute contains a modified expression that attaches a contract to the value, and using guard
directly would merely pass the expression through unchanged, without the contract attached.
For some more examples of expr/c
in action, see Contracts on Macro Sub-expressions.
Upvotes: 5