如何强制执行此结构中字段的类型?
#lang racket
(struct Car (model year))
我尝试过使用合同(但由于我是球拍新手,这个显然不起作用......:P)
(provide (contract-out
[Car (string? integer? . -> . Car?)]))
示例:这成功但它不应该......
(define my-car (Car 2008 "A3"))
可悲的是,它似乎没有写在任何地方如何完成这项工作。
如何强制执行此结构中字段的类型?
#lang racket
(struct Car (model year))
我尝试过使用合同(但由于我是球拍新手,这个显然不起作用......:P)
(provide (contract-out
[Car (string? integer? . -> . Car?)]))
示例:这成功但它不应该......
(define my-car (Car 2008 "A3"))
可悲的是,它似乎没有写在任何地方如何完成这项工作。
我认为您至少达到了一个,也许是以下两个:
使用(provide (contract-out ....))
意味着合同仅适用于模块边界——仅适用于该模块的其他模块require
。因此,如果您的测试示例位于同一模块中,则合同将不适用。相反,您可以使用define/contract
使合同适用于事物本身,无论是在定义它的模块中,还是在您定义的模块之外provide
。
s有一种特殊的合同形式,struct
您可以在其中为每个字段指定一个合同。您在上面尝试的只是构造函数上的合约。尽管这可能是您想要的,但请考虑使用合同struct
代替。
结合两者你可以做:
;; Define the contract on the struct itself.
;; Contract is used even within this module.
(provide car)
(define-struct/contract car ([model string?]
[year integer?]))
如果您确实希望合同仅适用于模块边界,那么您将使用:
;; Define the contract only as `provide`d.
;; Contract is used only for code `require`-ing this module.
(provide (contract-out (struct car ([model string?]
[year integer?]))))
(struct car (model year))
ps FWIW 在 Racket 中的常见样式是不将结构名称大写 -car
不是Car
。
更新:只是为了更清楚地说明差异:
#lang racket
(module mod racket
(provide car0)
(define-struct/contract car0 ([model string?]
[year integer?]))
(car0 "foo" "bar") ;; gives contract violation
;; because contract on struct itself
(struct car1 (model year))
(provide (contract-out (struct car1 ([model string?]
[year integer?]))))
(car1 "foo" "bar") ;; does NOT give contract violation
;; because contract only on the `provide`
)
(require 'mod)
(car0 "foo" "bar") ;; gives contract violation
(car1 "foo" "bar") ;; gives contract violation