我定义了一个true?与球拍/列表中的计数一起使用的函数.
(define (true? expr)
(and (boolean? expr) expr #t))
Run Code Online (Sandbox Code Playgroud)
我注意到我可以提供数字参数,我的功能很乐意返回#f.
> (true? 6)
#f
Run Code Online (Sandbox Code Playgroud)
所以,我想我会探索使用球拍合约来使非布尔参数在合同违规中返回错误.所以我把这个代码放在我的文件的顶部:
(provide (contract-out
[true? (-> boolean? boolean?)]))
Run Code Online (Sandbox Code Playgroud)
但是,在添加合同后,我仍然在球拍REPL中获得与上述相同的行为.我不明白这是怎么回事.我错过了什么?
dyo*_*yoo 21
合同通常在模块之间强制执行.所以你必须从外部角度尝试它.但是,REPL适用于您正在使用的模块内部.
从外部测试的一种简单方法是使用测试子模块.例如:
#lang racket
(define (true? expr)
(and (boolean? expr) expr #t))
(provide (contract-out
[true? (-> boolean? boolean?)]))
(module* test racket/base
(require (submod "..")
rackunit)
(check-true (true? #t))
(check-false (true? #f))
(check-exn exn:fail:contract? (lambda () (true? 3))))
Run Code Online (Sandbox Code Playgroud)
更改合同并在DrRacket中重新运行,您应该在此处看到您的合同生效,因为test此处的模块被视为合同的外部客户.
或者,制作另一个require第一个文件,然后你也可以看到合同的效果.如果调用了第一个文件true-test.rkt,那么您可以创建另一个模块,然后:
#lang racket
(require "true-test.rkt")
(true? 42) ;; And _this_ should also raise a contract error.
Run Code Online (Sandbox Code Playgroud)
Asu*_*awa 14
Danny Yoo给出了一个很好的答案.我只想扩展它,并注意到Racket确实为您提供了更强的合同执行地点(即合同边界的位置).例如,您可以使用以下define/contract表单:
-> (define/contract (true? expr)
(-> boolean? boolean?)
(and (boolean? expr) expr #t))
Run Code Online (Sandbox Code Playgroud)
这将在定义true?和所有其他代码之间建立合同检查:
-> (true? "foo")
; true?: contract violation
; expected: boolean?
; given: "foo"
; in: the 1st argument of
; (-> boolean? boolean?)
; contract from: (function true?)
; blaming: top-level
; at: readline-input:1.18
; [,bt for context]
Run Code Online (Sandbox Code Playgroud)
define/contract如果我想在REPL上测试与合同相关的东西,我觉得特别有用,我并不总是有一个模块.但是,这contract-out是默认建议,因为在模块边界检查合同通常是一个不错的选择.