首先,我为初学者问题道歉。我是一名经验丰富的开发人员,但对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?
以使其违反。我现在要寻找的是了解这里发生了什么。
提前感谢您的帮助!
答案 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))
由于您需要同时使用c1
和c2
的合同,因此我们需要采用不同的方法。让我们来看看如何将两个谓词组合成一个简单的谓词。
(and/p p1 p2)
应该是
的简称(lambda (x)
(and (p1 x) (p2 x)))
这里and
用于谓词返回的值 - 而不是谓词本身。
构造and/c
的工作方式类似于and/p
,但契约的表示比谓词更复杂。但原则是相同的。
是
的缩写(let ([t c1])
(if t
t
c2))