racket-使用模式匹配过程定义语法类
我试图定义语法类来匹配一个参数,这个参数是过程 我知道如何匹配标识符、表达式和其他语法类 这是我的样本:racket-使用模式匹配过程定义语法类,racket,Racket,我试图定义语法类来匹配一个参数,这个参数是过程 我知道如何匹配标识符、表达式和其他语法类 这是我的样本: (define-syntax-class model-property #:description "a model property" #:attributes (name datatype guard) (pattern name:id #:with datatype #`null #:with guard #'
(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])
)
我想用类似于:guard-guard:procedure
的内容替换:guard-guard:expr
我尝试过
(define-syntax-class model-property-guard
#:description "a property guard"
(pattern guard:expr
#:fail-when (procedure? #'guard)
"property guard should be procedure."))
可能吗?如何执行?宏在程序执行之前的编译时运行。在编译时,您无法知道表达式将生成哪种类型的值,因为信息根本不存在。(从理论上讲,您可以使用静态类型系统在语言中检查这样的内容,但是,
#lang racket
是动态类型的。)
您可以做的一件事是将约定放在表达式上,以便在约定不匹配时引发运行时错误。为此目的,提供了一个。您可以这样使用它:
(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)
将成功生成#
,而写入(m add1)
将在运行时失败并违反合同:
m: contract violation
expected: procedure?
given: 1
in: procedure?
请注意,扩展必须在扩展中使用guard.c
!c
属性包含一个修改过的表达式,该表达式将契约附加到值,直接使用guard
只会将表达式传递给unchanged,而不附加契约
有关正在运行的expr/c
的更多示例,请参阅