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