添加了外包合同的合同未执行

时间:2018-07-02 05:09:21

标签: racket

我需要解释为什么这种“外包”不起作用。 它只应返回正值,但仍接受负值。谁能解释?谢谢。

#lang racket


(struct account (balance))

(provide (contract-out
     [balance (-> account? number?)]
     [deposit (-> account? positive-num? account?)]))

(define new-account (account 0))

(define (positive-num? n)
  (cond [(not (number? n)) #f]
    [(> n 0) #t]))

(define (balance acc)
  (account-balance acc))

(define (deposit acc amt)
  (account (+ (account-balance acc) amt)))

(displayln (balance (deposit new-account -10)))

1 个答案:

答案 0 :(得分:2)

编写的程序存在两个问题。

首先,您的positive-num?谓词是错误的。尝试使用负数-您将不会获得#f的回馈。您的实现将使(positive-num? -10)产生#<void>(因为没有cond子句匹配),它不是#f,因此是真实的。您可以将positive-num?的主体重写为简单的(and (number? n) (> n 0)),这既清楚又正确,但是您也可以完全废弃自定义positive-num?谓词,而仅使用合同{{1} }。

代码的第二个问题更加微妙。给值赋予合同时,合同会附在合同边界上。只要在合同边界外使用值,合同就会强制执行,但合同边界内不会强制执行。这是因为,在合同范围内,您是直接使用该值,而不是附带合同的值。

使用(and/c real? positive?)时,合同边界是提供标识符的模块。在模块外部,合同是强制执行的,而在模块内部则不是。因此,由于您的整个程序都在一个模块中,因此合同永远都没有关系。

要查看实际效果,请尝试一个由多个模块组成的程序:

contract-out

由于合同规定的定义已移至单独的子模块中,并且由于对#lang racket (module bank racket (provide (contract-out [balance (-> account? number?)] [deposit (-> account? (and/c real? positive?) account?)] [new-account account?])) (struct account (balance)) (define new-account (account 0)) (define (balance acc) (account-balance acc)) (define (deposit acc amt) (account (+ (account-balance acc) amt)))) (require 'bank) (displayln (balance (deposit new-account -10))) 的调用在该子模块之外,因此上述代码引发了合同违约:

deposit

如果想要要在同一模块中执行的合同,则需要使用一种表格,该表格创建的合同边界比deposit: contract violation expected: a number strictly greater than 0 given: -10 in: the 2nd argument of (-> account? (and/c real? positive?) account?) contract from: (anonymous-module bank) blaming: anonymous-module (assuming the contract is correct) at: unsaved-editor:6.13 更细。 define/contract是一种这样的形式,它在定义本身与定义主体外部的所有内容之间建立了边界:

contract-out

现在,即使用法和定义在同一模块中,也会显示违反合同的情况。

有关合同边界以及为什么要选择另一种形式的更多详细信息,请参见《球拍指南》中的Contracts and Boundaries

相关问题