宏在编译时运行,在程序执行之前。在编译时,您不能知道表达式将产生哪种类型的值,这些信息根本不存在。(理论上,你可以用静态类型系统在语言中检查这样的东西,但是
#lang racket
是动态类型。)
有件事你
可以
do是将协定放在表达式上,以便在协定不匹配时引发运行时错误。这个
expr/c
syntax class
为此目的提供。您可以这样使用它:
(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]))
使用上述定义,写作
(m add1)
将成功生产
#<procedure:add1>
,同时写作
(m 1)
将在运行时因违反合同而失败:
m: contract violation
expected: procedure?
given: 1
in: procedure?
注意膨胀
必须
使用
guard.c
在扩张中!这个
c
属性包含将协定附加到值的已修改表达式,并使用
guard
直接通过不变的表达,没有附加合同。
更多关于
EXPR/C
实际操作中,请参见
Contracts on Macro Sub-expressions
.