更新
我完全错过了您在示例中使用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 的计算结果为真,则(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))