计划合同未被违反

时间:2016-10-21 18:37:54

标签: scheme racket contract

首先,我为初学者问题道歉。我是一名经验丰富的开发人员,但对Scheme很新。我创建了一个需要正整数的合约,但是当我提供一个实数时,合同不会被违反:

(define/contract (listofOne n)
  (-> (and integer? positive?) (listof integer?))
  (cond
    ((= n 0) '())
    (else (cons 1 (listofOne (- n 1))))))

(listofOne 12.5)

我预计合同会被违反,但我得到了无限循环和缓冲区溢出。为什么合同仍然没有违规?我的谓词中的第一个查询是integer?,所以我不会看到合同如何通过输入12.5返回true。

编辑:为了澄清,我不是在寻找一种方法来违反合同。我已经知道我可以使用和/ c,并且(感谢@soegaard)我可以撤消positive?integer?以使其违反。我现在要寻找的是了解这里发生了什么。

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:4)

更新

我完全错过您在示例中使用and而不是and/c。 试试这个:

#lang racket
(define/contract (listofOne n)
  (-> (and/c integer? positive?) (listof integer?))
  (cond
    ((= n 0) '())
    (else (cons 1 (listofOne (- n 1))))))

(listofOne 12.5)

结果:

listofOne: contract violation
  expected: integer?
  given: 12.5
  in: an and/c case of
      the 1st argument of
      (->
       (and/c integer? positive?)
       (listof integer?))
  contract from: (function listofOne)
  blaming: anonymous-module
   (assuming the contract is correct)
  at: unsaved-editor:2.18

第二次更新

以下是and的解释。

表格

(and c1 c2)

表示:

1. Evaluate `c1` giving a value `v`
2. If the value `v1` is false, 
   then the result of the `and`-expression is false.
   (note that `c2` is not evaluated)
3. If the value `v1` is non-false, 
   then evaluate the expression `c2` giving a value `v2`.
4. The result of the and-expressions is v2.

注意:如果c1的计算结果为true,则(and c1 c2)会得到与c2相同的结果。 这尤其意味着如果c1是合同(这是一个非假值) 然后(and c1 c2)会得到与c2相同的结果。

在您的示例(and integer? positive?)中,结果与positive?相同。

另请注意,这意味着(-> (and integer? positive?) (listof integer?))(-> positive? (listof integer?))的工作方式相同。

在代码中:

(and c1 c2)

相同
(let ([v1 c1])
  (if v1
      (let ([v2 c2])
         v2)
      #f))

由于您需要同时使用c1c2的合同,因此我们需要采用不同的方法。让我们来看看如何将两个谓词组合成一个简单的谓词。

(and/p p1 p2)

应该是

的简称
(lambda (x)
  (and (p1 x) (p2 x)))

这里and用于谓词返回的值 - 而不是谓词本身。

构造and/c的工作方式类似于and/p,但契约的表示比谓词更复杂。但原则是相同的。

的缩写
(let ([t c1])
  (if t
      t
      c2))