fixed some typos, and in the process rewrote some prose

This commit is contained in:
Matthias Felleisen 2010-11-02 15:47:58 -04:00
parent b212a4a39d
commit c83cf15695

View File

@ -580,73 +580,64 @@ symbols, and that return a symbol.
[_ (id ...) contract-expr]] [_ (id ...) contract-expr]]
)]{ )]{
The @racket[->i] contract combinator is similar in shape to @racket[->*], with The @racket[->i] contract combinator differs from the @racket[->*]
two extensions: names have been added to each argument and combinator in that the support pre- and post-condition clauses and
result, which allows the contracts to depend on the values in that each argument and result is named. These names can then
of the arguments and results, and pre- and post-condition be used in the subcontracts and in the pre-/post-condition clauses.
expressions have been added in order to express contracts In short, contracts now express dependencies among arguments and results.
that are not naturally tied to a particular argument or
result.
The first subforms of a @racket[->i] contract covers the The first subforms of a @racket[->i] contract covers the mandatory and the
mandatory and the second (optional) subform covers the optional second subform covers the optional arguments. Following that is an optional
arguments. Following that is an rest-args contract, and an optional pre-condition. The pre-condition is
optional rest-args contract, and an optional introduced with the @racket[#:pre] keyword followed by the list of names on
pre-condition. The pre-condition is specified with which it depends.
the @racket[#:pre] keyword, and must be followed
with the argument variables that it depends on.
The @racket[dep-range] non-terminal covers The @racket[dep-range] non-terminal specifies the possible result
the possible result contracts. If it is contracts. If it is @racket[any], then any value is allowed. Otherwise, the
@racket[any], then any result (or results) are result contract pairs a name and a contract or a multiple values return
allowed. Otherwise, the result contract can be a name and a with names and contracts. In the last two cases, the range contract may be
result contract, or a multiple values return and, in either optionally followed by a post-condition; the post-condition expression is
of the last two cases, it may be optionally followed by a not allowed if the range contract is @racket[any]. Like the pre-condition,
post-condition (the post-condition expression is not allowed the post-condition must specify the variables on which it depends.
if the range is @racket[any]). Like the pre-condition, the
post-condition must specify the variables that it depends on.
Each of the @racket[id]s on an argument (including the rest Consider this sample contract:
argument) is visible in the pre- and post-conditions sub-expressions of
@racket[->i], as well as visible in any of the argument or
result contracts that have explicitly listed it as a dependent argument.
For example, this contract:
@racketblock[(->i ([x number?] @racketblock[(->i ([x number?]
[y (x) (>=/c x)]) [y (x) (>=/c x)])
[result (x y) (>=/c (+ x y))])] [result (x y) (and/c number? (>=/c (+ x y)))])]
accepts two arugment functions from numbers to numbers, so long It specifies a function of two arguments, both numbers. The contract on the
as the second argument is greater than the first and the result is second argument (@scheme[y]) demands that it is greater than the first
greater than the sum of the two arguments. In order for @racket[x] argument. The result contract promises a number that is greater than the
to be used in the contract for @racket[y], it must declare that, by sum of the two arguments. While the dependency specification for @scheme[y]
writing the @racket[(x)] following @racket[y]. Since @racket[x]'s signals that the argument contract depends on the value of the first
contract does not depend on anything else, it does not have argument, the dependency list for @scheme[result] indicates that the
the parenthesized list at all. contract depends on both argument values. @margin-note*{In general, an
empty list is (nearly) equivalent to not adding
a list at all except that the former is more expensive than the latter.}
Since the contract for @racket[x] does not depend on anything else, it does
not come with any dependency list, not even @scheme[()].
In general, an empty parenthesized list is (nearly) semantically The contract expressions are not evaluated in
equivalent to not adding a list at all, except that the former order. First, if there is no dependency for a given contract expression,
is more expensive than the latter. the contract expression is evaluated at the time that the @racket[->i]
expression is evaluated rather than the time when the function is called or
The contract expressions are not evaluated in the order that they are returns. These dependency-free contract expressions are evaluated in the
listed, for three reasons. First, the if there is no dependency for a given order in which they are listed.
contract expression (on either a result or an input), then the contract @;
expression is evaluated at the time that the @racket[->i] expression is
evaluated rather than the time when the function is called (or returns, in the case
of the result contract expressions).
Those, non-dependent contract expressions are evaluated in the order listed
in the program text.
Second, the dependent contract subexpressions are evaluated when the Second, the dependent contract subexpressions are evaluated when the
contracted function is called (or returns), in an order contracted function is called or returns in some order that satisfies the
that satisfies the dependencies. That is, if one of the arguments depends dependencies. That is, if a contract for an argument depends on the value
on another one, the dependent one is evaluated first (so that the argument, of some other contract, the former is evaluated first (so that the
with its contract checked, is available for the other). argument, with its contract checked, is available for the other). When
When there is no dependency between two arguments (or results) there is no dependency between two arguments (or the result and an
then the one that appears earlier in the source text is evaluated first. argument) then the contract that appears earlier in the source text is
Finally, if all of the identifier positions of the range contract are evaluated first.
@racket[_]s (underscores), then the range contract #;
expressions are evaluated when the function is called (and Finally, if all of the identifier positions of the range
the underscore is not bound in the range), after the argument contract are @racket[_]s (underscores), then the range contract expressions
contracts are evaluated and checked. (Otherwise the are evaluated when the function is called and the underscore is not bound
range expressions are evaluated when the function returns.) in the range, after the argument contracts are evaluated and
checked. Otherwise the range expressions are evaluated when the function
returns.
If there are optional arguments that are not supplied, then If there are optional arguments that are not supplied, then
the corresponding variables will be bound to a special value the corresponding variables will be bound to a special value