使用自定义谓词定义球拍合同

Defining racket contracts with a custom predicate

我刚刚开始了解合同(通过 exercism.io),所以我制定了一份合同:

[step1 (-> (and/c number?
                  less-than-one-hundred?)
            string?)]

认为我的意思是该函数将采用小于一百的数字(该函数定义为:

(define (less-than-one-hundred? n)
  (< n 100))

但是当我这样调用函数时:

(step1 100)

没有违约。我做错了什么?

合同仅在模块边界上强制执行。 这意味着如果您的表达式 (step1 100) 与您的合同在同一个模块中,则不会检查输入。

但是,如果您使用合同导出 step1,然后在另一个模块中导入 step1 并调用它,则会检查合同。

以下是 Soegaard 的回答的具体示例:

def-step1.rkt

#lang racket

(provide (contract-out
          [step1 (-> (and/c number?
                            less-than-one-hundred?)
                     string?)]))

(define (less-than-one-hundred? n)
  (< n 100))

(define (step1 x) "")

使用-step1.rkt

#lang racket

(require "def-step1.rkt")

(step1 100)

这会像您预期的那样产生违反合同的行为,特别是,它 归咎于 use-step1.rkt,"contract party" 与 def-step1.rkt 不同,其中合同来自:

step1: contract violation
  expected: less-than-one-hundred?
  given: 100
  in: an and/c case of
      the 1st argument of
      (->
       (and/c number? less-than-one-hundred?)
       string?)
  contract from: .../def-step1.rkt
  blaming: .../use-step1.rkt
   (assuming the contract is correct)