adjusted the guide to use ->i instead of ->d

This commit is contained in:
Robby Findler 2010-09-09 14:21:16 -05:00
parent d419e8c12a
commit 2d1c4d1601

View File

@ -13,7 +13,7 @@ The @racket[->] contract constructor works for functions that take a
fixed number of arguments and where the result contract is independent fixed number of arguments and where the result contract is independent
of the input arguments. To support other kinds of functions, Racket of the input arguments. To support other kinds of functions, Racket
supplies additional contract constructors, notably @racket[->*] and supplies additional contract constructors, notably @racket[->*] and
@racket[->d]. @racket[->i].
@ctc-section[#:tag "optional"]{Optional Arguments} @ctc-section[#:tag "optional"]{Optional Arguments}
@ -272,15 +272,16 @@ The following is an excerpt from an imaginary numerics module:
@racketblock[ @racketblock[
(provide/contract (provide/contract
[real-sqrt (->d ([argument (>=/c 1)]) [real-sqrt (->i ([argument (>=/c 1)])
() [result (argument) (<=/c argument)])])
[result (<=/c argument)])])
] ]
The contract for the exported function @racket[real-sqrt] uses the The contract for the exported function @racket[real-sqrt] uses the
@racket[->d] rather than @racket[->*] function contract. The ``d'' @racket[->i] rather than @racket[->*] function contract. The ``i''
stands for a @italic{dependent} contract, meaning the contract for the stands for an @italic{indy dependent} contract, meaning the contract for the
function range depends on the value of the argument. In this function range depends on the value of the argument. The appearance
of @racket[argument] in the line for @racket[result]'s contract means
that the result depends on the argument. In this
particular case, the argument of @racket[real-sqrt] is greater or particular case, the argument of @racket[real-sqrt] is greater or
equal to 1, so a very basic correctness check is that the result is equal to 1, so a very basic correctness check is that the result is
smaller than the argument. smaller than the argument.
@ -327,17 +328,17 @@ racket
(provide/contract (provide/contract
[create (amount/c . -> . account?)] [create (amount/c . -> . account?)]
[balance (account? . -> . amount/c)] [balance (account? . -> . amount/c)]
[withdraw (->d ([acc account?] [withdraw (->i ([acc account?]
[amt (and/c amount/c (<=/c (balance acc)))]) [amt (acc) (and/c amount/c (<=/c (balance acc)))])
() [result (acc amt)
[result (and/c account? (and/c account?
(lambda (res) (lambda (res)
(>= (balance res) (>= (balance res)
(- (balance acc) amt))))])] (- (balance acc) amt))))])]
[deposit (->d ([acc account?] [deposit (->i ([acc account?]
[amt amount/c]) [amt amount/c])
() [result (acc amt)
[result (and/c account? (and/c account?
(lambda (res) (lambda (res)
(>= (balance res) (>= (balance res)
(+ (balance acc) amt))))])]) (+ (balance acc) amt))))])])
@ -361,7 +362,7 @@ complicated constraints on @racket[balance] and @racket[deposit]. The
contract on the second argument to @racket[withdraw] uses contract on the second argument to @racket[withdraw] uses
@racket[(balance acc)] to check whether the supplied withdrawal amount @racket[(balance acc)] to check whether the supplied withdrawal amount
is small enough, where @racket[acc] is the name given within is small enough, where @racket[acc] is the name given within
@racket[->d] to the function's first argument. The contract on the @racket[->i] to the function's first argument. The contract on the
result of @racket[withdraw] uses both @racket[acc] and @racket[amt] to result of @racket[withdraw] uses both @racket[acc] and @racket[amt] to
guarantee that no more than that requested amount was withdrawn. The guarantee that no more than that requested amount was withdrawn. The
contract on @racket[deposit] similarly uses @racket[acc] and contract on @racket[deposit] similarly uses @racket[acc] and
@ -393,14 +394,13 @@ racket
(provide/contract (provide/contract
[create (amount/c . -> . account?)] [create (amount/c . -> . account?)]
[balance (account? . -> . amount/c)] [balance (account? . -> . amount/c)]
[withdraw (->d ([acc account?] [withdraw (->i ([acc account?]
[amt (and/c amount/c (<=/c (balance acc)))]) [amt (acc) (and/c amount/c (<=/c (balance acc)))])
() [result (acc amt) (mk-account-contract acc amt >= msg>)])]
[result (mk-account-contract acc amt >= msg>)])] [deposit (->i ([acc account?]
[deposit (->d ([acc account?]
[amt amount/c]) [amt amount/c])
() [result (acc amt)
[result (mk-account-contract acc amt <= msg<)])]) (mk-account-contract acc amt <= msg<)])])
(code:comment "section 3: the function definitions") (code:comment "section 3: the function definitions")
(define balance account-balance) (define balance account-balance)
@ -416,15 +416,14 @@ racket
@ctc-section[#:tag "arrow-d-eval-order"]{Checking State Changes} @ctc-section[#:tag "arrow-d-eval-order"]{Checking State Changes}
The @racket[->d] contract combinator can also ensure that a The @racket[->i] contract combinator can also ensure that a
function only modifies state according to certain function only modifies state according to certain
constraints. For example, consider this contract constraints. For example, consider this contract
(it is a slightly simplified from the function (it is a slightly simplified from the function
@racket[preferences:add-panel] in the framework): @racket[preferences:add-panel] in the framework):
@racketblock[ @racketblock[
(->d ([parent (is-a?/c area-container-window<%>)]) (->i ([parent (is-a?/c area-container-window<%>)])
() [_ (parent)
[_
(let ([old-children (send parent get-children)]) (let ([old-children (send parent get-children)])
(λ (child) (λ (child)
(andmap eq? (andmap eq?
@ -459,13 +458,13 @@ racket
(define (get-x) x) (define (get-x) x)
(define (f) (set! x (cons 'f x))) (define (f) (set! x (cons 'f x)))
(provide/contract (provide/contract
[f (->d () () [_ (begin (set! x (cons 'ctc x)) any/c)])] [f (->i () [_ (begin (set! x (cons 'ctc x)) any/c)])]
[get-x (-> (listof symbol?))]) [get-x (-> (listof symbol?))])
] ]
If you were to require this module, call @racket[f], then If you were to require this module, call @racket[f], then
the result of @racket[get-x] would be @racket['(f ctc)]. In the result of @racket[get-x] would be @racket['(f ctc)]. In
contrast, if the contract for @racket[f] were contrast, if the contract for @racket[f] were
@racketblock[(->d () () [res (begin (set! x (cons 'ctc x)) any/c)])] @racketblock[(->i () [res (begin (set! x (cons 'ctc x)) any/c)])]
(only changing the underscore to @racket[res]), then (only changing the underscore to @racket[res]), then
the result of @racket[get-x] would be @racket['(ctc f)]. the result of @racket[get-x] would be @racket['(ctc f)].
@ -514,7 +513,7 @@ using @racket[->*]:
Now, suppose that we also want to ensure that the first result of Now, suppose that we also want to ensure that the first result of
@racket[split] is a prefix of the given word in list format. In that @racket[split] is a prefix of the given word in list format. In that
case, we need to use the @racket[->d] contract combinator: case, we need to use the @racket[->i] contract combinator:
@racketblock[ @racketblock[
(define (substring-of? s) (define (substring-of? s)
(flat-named-contract (flat-named-contract
@ -525,12 +524,11 @@ Now, suppose that we also want to ensure that the first result of
(equal? (substring s 0 (string-length s2)) s2))))) (equal? (substring s 0 (string-length s2)) s2)))))
(provide/contract (provide/contract
[split (->d ([fl (listof char?)]) [split (->i ([fl (listof char?)])
() (values [s (fl) (substring-of (list->string fl))]
(values [s (substring-of (list->string fl))]
[c (listof char?)]))]) [c (listof char?)]))])
] ]
Like @racket[->*], the @racket[->d] combinator uses a function over the Like @racket[->*], the @racket[->i] combinator uses a function over the
argument to create the range contracts. Yes, it doesn't just return one argument to create the range contracts. Yes, it doesn't just return one
contract but as many as the function produces values: one contract per contract but as many as the function produces values: one contract per
value. In this case, the second contract is the same as before, ensuring value. In this case, the second contract is the same as before, ensuring
@ -542,9 +540,8 @@ This contract is expensive to check, of course. Here is a slightly
cheaper version: cheaper version:
@racketblock[ @racketblock[
(provide/contract (provide/contract
[split (->d ([fl (listof char?)]) [split (->i ([fl (listof char?)])
() (values [s (fl) (string-len/c (length fl))]
(values [s (string-len/c (length fl))]
[c (listof char?)]))]) [c (listof char?)]))])
] ]
@ -613,7 +610,7 @@ because the given function accepts only one argument.
@racketblock[ @racketblock[
(provide/contract (provide/contract
[n-step [n-step
(->d ([proc (->i ([proc (inits)
(and/c (unconstrained-domain-> (and/c (unconstrained-domain->
(or/c false/c number?)) (or/c false/c number?))
(λ (f) (procedure-arity-includes? (λ (f) (procedure-arity-includes?