我正在尝试定义与过程参数相匹配的语法类。
我知道如何匹配标识符,表达式,另一个语法类。
这是我的示例:
(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])
)
Run Code Online (Sandbox Code Playgroud)
我想#:guard guard:expr
用类似的东西代替#:guard guard:procedure
我尝试过
(define-syntax-class model-property-guard
#:description "a property guard"
(pattern guard:expr
#:fail-when (procedure? #'guard)
"property guard should be procedure."))
Run Code Online (Sandbox Code Playgroud)
可能吗?怎么样?
宏在程序执行之前在编译时运行。在编译时,您不知道表达式将产生什么样的值-信息根本不存在。(从理论上讲,您可以使用具有静态类型系统的语言来检查此类内容,但#lang racket
可以动态键入。)
您可以做的一件事是将契约放在表达式上,以便在契约不匹配时引发运行时错误。该expr/c
语法类被用于此目的。您可以这样使用它:
(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]))
Run Code Online (Sandbox Code Playgroud)
使用以上定义,写入(m add1)
将成功产生#<procedure:add1>
,而写入(m 1)
将在运行时因违反合同而失败:
m: contract violation
expected: procedure?
given: 1
in: procedure?
Run Code Online (Sandbox Code Playgroud)
注意扩展必须guard.c
在扩展中使用!该c
属性包含一个修改后的表达式,该表达式将合同附加到该值,并且guard
直接使用该表达式将仅通过不变的表达式,而无需附加合同。
有关expr/c
实际操作的更多示例,请参见宏子表达式上的协定。
归档时间: |
|
查看次数: |
82 次 |
最近记录: |