diff --git a/collects/scribblings/guide/contracts-general-function.scrbl b/collects/scribblings/guide/contracts-general-function.scrbl index 08bcf82919..5d9cce79b7 100644 --- a/collects/scribblings/guide/contracts-general-function.scrbl +++ b/collects/scribblings/guide/contracts-general-function.scrbl @@ -62,7 +62,7 @@ arguments: @racket[char?]. } @item{The last one is a single contract: the result of the function.} ] - Note if a default value does not satisfy a contract, you won't get a + Note that if a default value does not satisfy a contract, you won't get a contract error for this interface. If you can't trust yourself to get the initial value right, you need to communicate the initial value across a boundary. @@ -71,7 +71,7 @@ arguments: @racket[char?]. } The @racket[max] operator consumes at least one real number, but it accepts any number of additional arguments. You can write other such - functions using a ``rest'' argument, such as in @racket[max-abs]: + functions using a @tech{rest argument}, such as in @racket[max-abs]: @margin-note{See @secref["rest-args"] for an introduction to rest arguments.} @@ -424,7 +424,7 @@ racket The @racket[->i] contract combinator can also ensure that a function only modifies state according to certain constraints. For example, consider this contract -(it is a slightly simplified from the function +(it is a slightly simplified version from the function @racket[preferences:add-panel] in the framework): @racketblock[ (->i ([parent (is-a?/c area-container-window<%>)]) @@ -614,7 +614,7 @@ because the given function accepts only one argument. The correct contract uses the @racket[unconstrained-domain->] combinator, which specifies only the range of a function, not its domain. It is then possible to combine this contract with an arity test to - specify the correct @racket[n-step]'s contract: + specify the correct contract for @racket[n-step]: @racketblock[ (provide (contract-out diff --git a/collects/scribblings/guide/contracts-simple-function.scrbl b/collects/scribblings/guide/contracts-simple-function.scrbl index 242388cb4f..3767ea1203 100644 --- a/collects/scribblings/guide/contracts-simple-function.scrbl +++ b/collects/scribblings/guide/contracts-simple-function.scrbl @@ -10,7 +10,7 @@ A mathematical function has a @deftech{domain} and a @deftech{range}. The domain indicates the kind of values that the function can accept as arguments, and the range indicates the kind of -values that it produces. The conventional notation for a describing a +values that it produces. The conventional notation for describing a function with its domain and range is @racketblock[ @@ -63,7 +63,7 @@ parties is to blame. If a client module were to apply @racket[deposit] to @racket['millions], it would violate the contract. The contract-monitoring system would -catch this violation and blame client for breaking the contract with +catch this violation and blame the client for breaking the contract with the above module. In contrast, if the @racket[balance] function were to return @racket['broke], the contract-monitoring system would blame the server module. @@ -75,7 +75,7 @@ combinator}, which combines other contracts to form a contract. @section{Styles of @racket[->]} -If you are used to mathematical function, you may prefer a contract +If you are used to mathematical functions, you may prefer a contract arrow to appear between the domain and the range of a function, not at the beginning. If you have read @|HtDP|, you have seen this many times. Indeed, you may have seen contracts such as these in other @@ -410,11 +410,11 @@ With this little change, the error message becomes quite readable: In general, each contract error message consists of six sections: @itemize[@item{a name for the function or method associated with the contract - and either the phrase ``contract violation'' or ``violated it's contract'' - depending on whether the contract was violated by the server or the - client; e.g. in the previous example: @lines[0 1]} - @item{a description of the precise aspect of the contract that was violated, @lines[1 1]} - @item{the complete contract plus a path into it showing which aspect was violated, @lines[2 2]} - @item{the module where the contract was put (or, more generally, the boundary that the contract mediates), @lines[4 1]} - @item{who was blamed, @lines[5 1]} - @item{and the source location where the contract appears. @lines[6 1]}] + and either the phrase ``contract violation'' or ``broke its contract'' + depending on whether the contract was violated by the client or the + server; e.g. in the previous example: @lines[0 1]} + @item{a description of the precise aspect of the contract that was violated, @lines[1 2]} + @item{the complete contract plus a path into it showing which aspect was violated, @lines[3 2]} + @item{the module where the contract was put (or, more generally, the boundary that the contract mediates), @lines[5 1]} + @item{who was blamed, @lines[6 1]} + @item{and the source location where the contract appears. @lines[7 1]}] diff --git a/collects/scribblings/guide/contracts-structure.scrbl b/collects/scribblings/guide/contracts-structure.scrbl index 0897c854ec..4b299d2f6b 100644 --- a/collects/scribblings/guide/contracts-structure.scrbl +++ b/collects/scribblings/guide/contracts-structure.scrbl @@ -166,7 +166,7 @@ racket (define (bst? b) (bst-between? b -inf.0 +inf.0)) -(provide (struct node (val left right))) +(provide (struct-out node)) (provide (contract-out [bst? (any/c . -> . boolean?)] [in? (number? bst? . -> . boolean?)])) @@ -195,19 +195,16 @@ that @racket[in?] looks at, we can still guarantee that the tree is at least partially well-formed, but without changing the complexity. -To do that, we need to use @racket[define-contract-struct] in place of -@racket[struct]. Like @racket[struct] (and more like -@racket[define-struct]), @racket[define-contract-struct] defines a -maker, predicate, and selectors for a new structure. Unlike -@racket[define-struct], it also defines contract combinators, in this -case @racket[node/c] and @racket[node/dc]. Also unlike -@racket[define-struct], it does not allow mutators, making its structs -always immutable. +To do that, we need to use @racket[struct/dc] to define +@racket[bst-between?]. Like @racket[struct/c], @racket[struct/dc] defines a +contract for a structure. Unlike +@racket[struct/c], it allows fields to be marked as lazy, so that +the contracts are only checked when the matching selector is called. +Also, it does not allow mutable fields to be marked as lazy. -The @racket[node/c] function accepts a contract for each +The @racket[struct/dc] form accepts a contract for each field of the struct and returns a contract on the -struct. More interestingly, the syntactic -form @racket[node/dc] allows us to write dependent +struct. More interestingly, @racket[struct/dc] allows us to write dependent contracts, i.e., contracts where some of the contracts on the fields depend on the values of other fields. We can use this to define the binary search tree contract: @@ -215,35 +212,38 @@ this to define the binary search tree contract: @racketmod[ racket -(define-contract-struct node (val left right)) - +(struct node (val left right)) + (code:comment "determines if `n' is in the binary search tree `b'") (define (in? n b) ... as before ...) - + (code:comment "bst-between : number number -> contract") (code:comment "builds a contract for binary search trees") (code:comment "whose values are between low and high") (define (bst-between/c low high) (or/c null? - (node/dc [val (between/c low high)] - [left (val) (bst-between/c low val)] - [right (val) (bst-between/c val high)]))) - + (struct/dc node [val (between/c low high)] + [left (val) #:lazy (bst-between/c low val)] + [right (val) #:lazy (bst-between/c val high)]))) + (define bst/c (bst-between/c -inf.0 +inf.0)) -(provide make-node node-left node-right node-val node?) +(provide (struct-out node)) (provide (contract-out [bst/c contract?] [in? (number? bst/c . -> . boolean?)])) ] -In general, each use of @racket[node/dc] must name the +In general, each use of @racket[struct/dc] must name the fields and then specify contracts for each field. In the above, the @racket[val] field is a contract that accepts values between @racket[low] and @racket[high]. The @racket[left] and @racket[right] fields are dependent on the value of the @racket[val] field, -indicated by their second sub-expressions. Their contracts +indicated by their second sub-expressions. They are +also marked with the @racket[#:lazy] keyword to indicate +that they should be checked only when the appropriate +accessor is called on the struct instance. Their contracts are built by recursive calls to the @racket[bst-between/c] function. Taken together, this contract ensures the same thing that @@ -263,8 +263,8 @@ body to be a contract and then optimizes that contract. @racketblock[ (define-opt/c (bst-between/c low high) (or/c null? - (node/dc [val (between/c low high)] - [left (val) (bst-between/c low val)] - [right (val) (bst-between/c val high)]))) + (struct/dc node [val (between/c low high)] + [left (val) #:lazy (bst-between/c low val)] + [right (val) #:lazy (bst-between/c val high)]))) ]