contract.ss: Contracts

To load: (require (lib "contract.ss"))

MzLib's contract.ss library defines new forms of expression that specify contracts and new forms of expression that attach contracts to values.

This section describes three classes of contracts: contracts for flat values (described in section 12.1), contracts for functions (described in section 12.2), and contracts for objects and classes (described in section 12.4).

In addition, this section describes how to establish a contract, that is, how to indicate that a particular contract should be enforced at a particular point in the program (in section 12.5).

12.1  Flat Contracts

A contract for a flat value can be a predicate that accepts the value and returns a boolean indicating if the contract holds.

(flat-contract predicate)      FLAT-CONTRACT

Constructs a contract from predicate.

(flat-named-contract type-name predicate)      FLAT-CONTRACT

For better error reporting, a flat contract can be constructed with flat-named-contract, a procedure that accepts two arguments. The first argument must be a string that describes the type that the predicate checks for. The second argument is the predicate itself.

any/c      FLAT-CONTRACT

any/c is a flat contract that accepts any value.

If you are using this predicate as the result portion of a function contract, consider using any instead. It behaves the same, but in that one restrictive context has better memory performance.

none/c      FLAT-CONTRACT

none/c is a flat contract that accepts no values.

(or/c contract ···)      OR/C

or/c accepts any number of predicates and higher-order contracts and returns a contract that accepts any value that any one of the contracts accepts, individually.

If all of the arguments are predicates or flat contracts, it returns a flat contract. If only one of the arguments is a higher-order contract, it returns a contract that just checks the flat contracts and, if they don't pass, applies the higher-order contract.

If there are multiple higher-order contracts, or/c uses contract-first-order-passes? to distinguish between them. More precisely, when an or/c is checked, it first checks all of the flat contracts. If none of them pass, it calls contract-first-order-passes? with each of the higher-order contracts. If only one returns true, or/c uses that contract. If none of them return true, it signals a contract violation. If more than one returns true, it signals an error indicating that the or/c contract is malformed.

or/c tests any values by applying the contracts in order, from left to right, with the exception that it always moves the non-flat contracts (if any) to the end, checking them last.

(and/c contract ···)      CONTRACT

and/c accepts any number of contracts and returns a contract that checks that accepts any value that satisfies all of the contracts, simultaneously.

If all of the arguments are predicates or flat contracts, and/c produces a flat contract.

and/c tests any values by applying the contracts in order, from left to right.

(not/c flat-contract)      FLAT-CONTRACT

not/c accepts a flat contracts or a predicate and returns a flat contract that checks the inverse of the argument.

(=/c number)      FLAT-CONTRACT

=/c accepts a number and returns a flat contract that requires the input to be a number and equal to the original input.

(>=/c number)      FLAT-CONTRACT

>=/c accepts a number and returns a flat contract that requires the input to be a number and greater than or equal to the original input.

(<=/c number)      FLAT-CONTRACT

<=/c accepts a number and returns a flat contract that requires the input to be a number and less than or equal to the original input.

(between/c number number)      FLAT-CONTRACT

between/c accepts two numbers and returns a flat contract that requires the input to between the two numbers (or equal to one of them).

(>/c number)      FLAT-CONTRACT

>/c accepts a number and returns a flat contract that requires the input to be a number and greater than the original input.

(</c number)      FLAT-CONTRACT

</c accepts a number and returns a flat contract that requires the input to be a number and less than the original input.

(integer-in number number)      FLAT-CONTRACT

integer-in accepts two numbers and returns a flat contract that recognizes if integers between the two inputs, or equal to one of its inputs.

(real-in number number)      FLAT-CONTRACT

real-in accepts two numbers and returns a flat contract that recognizes real numbers between the two inputs, or equal to one of its inputs.

natural-number/c      FLAT-CONTRACT

natural-number/c is a contract that recognizes natural numbers (i.e., an integer that is either positive or zero).

(string/len number)      FLAT-CONTRACT

string/len accepts a number and returns a flat contract that recognizes strings that have fewer than that number of characters.

false/c      FLAT-CONTRACT

false/c is a flat contract that recognizes #f.

printable/c      FLAT-CONTRACT

printable/c is a flat contract that recognizes values that can be written out and read back in with write and read.

(one-of/c value ···1)      FLAT-CONTRACT

one-of/c accepts any number of atomic values and returns a flat contract that recognizes those values, using eqv? as the comparison predicate. For the purposes of one-of/c, atomic values are defined to be: characters, symbols, booleans, null keywords, numbers, void, and undefined.

(symbols symbol ···1)      FLAT-CONTRACT

symbols accepts any number of symbols and returns a flat contract that recognizes those symbols.

(is-a?/c class-or-interface)      FLAT-CONTRACT

is-a?/c accepts a class or interface and returns a flat contract that recognizes if objects are subclasses of the class or implement the interface.

(implementation?/c interface)      FLAT-CONTRACT

implementation?/c accepts an interface and returns a flat contract that recognizes if classes are implement the given interface.

(subclass?/c class)      FLAT-CONTRACT

subclass?/c accepts a class and returns a flat-contract that recognizes classes that are subclasses of the original class.

(listof flat-contract)      FLAT-CONTRACT

listof accepts a flat contract (or a predicate which is converted to a flat contract) and returns a flat contract that checks for lists whose elements match the original flat contract.

(list-immutableof contract)      CONTRACT

list-immutableof accepts a contract (or a predicate which is converted to a flat contract) and returns a contract that checks for immutable lists whose elements match the original contract. In contrast to listof, list-immutableof accepts arbitrary contracts, not just flat contracts.

Beware, however, that when a value is applied to this contract, the result will not be eq? to the input.

(vectorof flat-contract)      FLAT-CONTRACT

vectorof accepts a flat contract (or a predicate which is converted to a flat contract via flat-contract) and returns a predicate that checks for vectors whose elements match the original flat contract.

(vector-immutableof contract)      CONTRACT

vector-immutableof accepts a contract (or a predicate which is converted to a flat contract) and returns a contract that checks for immutable lists whose elements match the original contract. In contrast to vectorof, vector-immutableof accepts arbitrary contracts, not just flat contracts.

Beware, however, that when a value is applied to this contract, the result will not be eq? to the input.

(vector/c flat-contract ···)      FLAT-CONTRACT

vector/c accepts any number of flat contracts (or predicates which are converted to flat contracts via flat-contract) and returns a flat-contract that recognizes vectors. The number of elements in the vector must match the number of arguments supplied to vector/c and the elements of the vector must match the corresponding flat contracts.

(vector-immutable/c contract ···)      CONTRACT

vector-immutable/c accepts any number of contracts (or predicates which are converted to flat contracts via flat-contract) and returns a contract that recognizes vectors. The number of elements in the vector must match the number of arguments supplied to vector-immutable/c and the elements of the vector must match the corresponding contracts.

In contrast to vector/c, vector-immutable/c accepts arbitrary contracts, not just flat contracts. Beware, however, that when a value is applied to this contract, the result will not be eq? to the input.

(box/c flat-contract)      FLAT-CONTRACT

box/c accepts a flat contract (or predicate that is converted to a flat contract via flat-contract) and returns a flat contract that recognizes for boxes whose contents match box/c's argument.

(box-immutable/c contract)      CONTRACT

box-immutable/c one contracts (or a predicate that is converted to a flat contract via flat-contract) and returns a contract that recognizes boxes. The contents of the box must match the contract passed to box-immutable/c.

In contrast to box/c, box-immutable/c accepts an arbitrary contract, not just a flat contract. Beware, however, that when a value is applied to this contract, the result will not be eq? to the input.

(cons/c flat-contract flat-contract)      FLAT-CONTRACT

cons/c accepts two flat contracts (or predicates that are converted to flat contracts via flat-contract) and returns a flat contract that recognizes cons cells whose car and cdr correspond to cons/c's two arguments.

(cons-immutable/c contract contract)      CONTRACT

cons-immutable/c accepts two contracts (or predicates that are converted to flat contracts via flat-contract) and returns a contract that recognizes immutable cons cells whose car and cdr correspond to cons-immutable/c's two arguments. In contrast to cons/c, cons-immutable/c accepts arbitrary contracts, not just flat contracts.

Beware, however, that when a value is applied to this contract, the result will not be eq? to the input.

(list/c flat-contract ···)      FLAT-CONTRACT

list/c accepts an arbitrary number of flat contracts (or predicates that are converted to flat contracts via flat-contract) and returns a flat contract that recognizes for lists whose length is the same as the number of arguments to list/c and whose elements match those arguments.

(list-immutable/c contract ···)      CONTRACT

list-immutable/c accepts an arbitrary number of contracts (or predicates that are converted to flat contracts via flat-contract) and returns a contract that recognizes for lists whose length is the same as the number of arguments to list-immutable/c and whose elements match those contracts.

In contrast to list/c, list-immutable/c accepts arbitrary contracts, not just flat contracts. Beware, however, that when a value is applied to this contract, the result will not be eq? to the input.

(syntax/c flat-contract)      FLAT-CONTRACT

syntax/c accepts a flat contract and produces a flat contract that recognizes syntax objects whose contents match the argument to syntax/c.

(struct/c struct-name flat-contract ...)      FLAT-CONTRACT

struct/c accepts a struct name and as many flat contracts as there are fields in the named struct. It returns a contract that accepts instances of that struct whose fields match the given contracts.

(flat-rec-contract name flat-contract ···)      SYNTAX

Each flat-rec-contract form constructs a flat recursive contract. The first argument is the name of the contract and the following arguments are flat contract expressions that may refer to name.

As an example, this contract:

   (flat-rec-contract sexp
     (cons/c sexp sexp)
     number?
     symbol?)

is a flat contract that checks for (a limited form of) s-expressions. It says that an sexp is either two sexp combined with cons, or a number, or a symbol.

Note that if the contract is applied to a circular value, contract checking will not terminate.

(flat-murec-contract ([name flat-contract ···] ···) body ···)      SYNTAX

The flat-murec-contract form is a generalization of flat-rec-contracts for defining several mutually recursive flat contracts simultaneously.

Each of the names is visible in the entire flat-murec-contract and the result of the final body expression is the result of the entire form.

Note that if the contract is applied to a circular value, contract checking will not terminate.

12.2  Function Contracts

->

This section describes the contract constructors for function contracts. This is their shape:

contract-expr ::==
 | (case-> arrow-contract-expr ···)
 | arrow-contract-expr

arrow-contract-expr ::== 
 | (-> expr ··· expr)
 | (-> expr ··· any)
 | (-> expr ··· (values expr ···))

 | (->* (expr ···) (expr ···))
 | (->* (expr ···) any)
 | (->* (expr ···) expr (expr ···))
 | (->* (expr ···) expr any)

 | (->d expr ··· expr)
 | (->d* (expr ···) expr)
 | (->d* (expr ···) expr expr)

 | (->r ((id expr) ···) expr)
 | (->r ((id expr) ···) any)
 | (->r ((id expr) ···) (values (id expr) ···))
 | (->r ((id expr) ···) id expr expr)
 | (->r ((id expr) ···) id expr any)
 | (->r ((id expr) ···) id expr (values (id expr) ···))

 | (->pp ((id expr) ···) pre-expr expr res-id post-expr)
 | (->pp ((id expr) ···) pre-expr any)
 | (->pp ((id expr) ···) pre-expr (values (id expr) ···) post-expr)

 | (->pp-rest ((id expr) ···) id expr pre-expr expr res-id post-expr)
 | (->pp-rest ((id expr) ···) id expr pre-expr any)
 | (->pp-rest ((id expr) ···) id expr pre-expr (values (id expr) ···) post-expr)

 | (opt-> (expr ···) (expr ···) expr)
 | (opt->* (expr ···) (expr ···) any)
 | (opt->* (expr ···) (expr ···) (expr ···))

where expr is any expression.

(-> expr ···)      SYNTAX

(-> expr ···any)      SYNTAX

The -> contract is for functions that accept a fixed number of arguments and return a single result. The last argument to -> is the contract on the result of the function and the other arguments are the contracts on the arguments to the function. Each of the arguments to -> must be another contract expression or a predicate. For example, this expression:

(integer? boolean? . -> . integer?)

is a contract on functions of two arguments. The first must be an integer and the second a boolean and the function must return an integer. (This example uses MzScheme's infix notation so that the -> appears in a suggestive place; see section 11.2.4 in PLT MzScheme: Language Manual).

If any is used as the last argument to ->, no contract checking is performed on the result of the function, and tail-recursion is preserved. Except for the memory performance, this is the same as using any/c in the result.

The final case of -> expressions treats values as a local keyword - that is, you may not return multiple values to this position, instead if the word values syntactically appears in the in the last argument to -> the function is treated as a multiple value return.

(->* (expr ···) (expr ···))      SYNTAX

(->* (expr ···) any)      SYNTAX

(->* (expr ···) expr (expr ···))      SYNTAX

(->* (expr ···) expr any)      SYNTAX

The ->* expression is for functions that return multiple results and/or have rest arguments. If two arguments are supplied, the first is the contracts on the arguments to the function and the second is the contract on the results of the function. These situations are also covered by ->.

If three arguments are supplied, the first argument contains the contracts on the arguments to the function (excluding the rest argument), the second contains the contract on the rest argument to the function and the final argument is the contracts on the results of the function. The final argument can be any which, like -> means that no contract is enforced on the result of the function and tail-recursion is preserved.

(->d expr ···)      SYNTAX

(->d* (expr ···) expr))      SYNTAX

(->d* (expr ···) expr expr)      SYNTAX

The ->d and ->d* contract constructors are like their d-less counterparts, except that the result portion is a function that accepts the original arguments to the function and returns the range contracts. The range contract function for ->d* must return multiple values: one for each result of the original function. As an example, this is the contract for sqrt:

(number? 
 . ->d .
 (lambda (in)
   (lambda (out)
     (and (number? out)
          (< (abs (- (* out out) in)) 0.01)))))

It says that the input must be a number and that the difference between the square of the result and the original number is less than 0.01.

(->r ([id expr] ···) expr)      SYNTAX

The ->r contract allows you to build a contract where the arguments to a function may all depend on each other and the result of the function may depend on all of the arguments.

Each of the ids names one of the actual arguments to the function with the contract. Each of the names is available to all of the other contracts. For example, to define a function that accepts three arguments where the second argument and the result must both be between the first, you might write:

(->r ([x number?] [y (and/c (>=/c x) (<=/c z))] [z number?])
     (and/c number? (>=/c x) (<=/c z)))

(->r ([id expr] ···) any)      SYNTAX

This variation on ->r does not check anything about the result of the function, which preserves tail recursion.

(->r ([id expr] ···) (values [id expr] ...))      SYNTAX

This variation on ->r allows multiple value return values. The ids for the domain are bound in all of the exprs, but the ids for the range (the ones inside values) are only bound in the exprs inside the values.

As an example, this contract:

(->r () (values [x number?]
                [y (and/c (>=/c x) (<=/c z))]
                [z number?]))

matches functions that accept no arguments and that return three numeric values that are in ascending order.

(->r ([id expr] ···) id expr expr)      SYNTAX

(->r ([id expr] ···) id expr any)      SYNTAX

(->r ([id expr] ···) id expr (values [id expr] ...))      SYNTAX

These three forms of the ->r contract are just like the previous ones, except that the functions they matches must accept arbitrarily many arguments. The extra id and the expr just following it specify the contracts on the extra arguments. The value of id will alway be a list (of the extra arguments).

(->pp ([id expr] ···) pre-expr expr res-id post-expr)      SYNTAX

(->pp ([id expr] ···) pre-expr any)      SYNTAX

(->pp ([id expr] ···) pre-expr (values [id expr] ...) post-expr)      SYNTAX

(->pp-rest ([id expr] ···) id expr pre-expr expr res-id post-expr)      SYNTAX

(->pp-rest ([id expr] ···) id expr pre-expr any)      SYNTAX

(->pp-rest ([id expr] ···) id expr pre-expr (values [id expr] ...) post-expr)      SYNTAX

These six shapes of ->pp match up to the six shapes of ->r forms explained above, with the addition that the extra pre- and post-condition expressions must not evaluate to #f.

If the pre-condition evaluates to #f, the caller is blamed and if the post-condition expression evaluates to #f the function itself is blamed.

The argument variables are bound in the pre-expr and the post-expr and the variables in the values result clauses are bound in the post-expr.

Additionally, the variable res-id is bound to the result in the first ->pp case and in the first ->pp-rest case.

(case-> arrow-contract-expr ···)      CONTRACT-CASE->

The case-> expression constructs a contract for case-lambda function. It's arguments must all be function contracts, built by one of ->, ->d, ->*, or ->d*.

(opt-> (req-contracts ···) (opt-contracts ···) res-contract))      SYNTAX

(opt->* (req-contracts ···) (opt-contracts ···) (res-contracts ···))      SYNTAX

(opt->* (req-contracts ···) (opt-contracts ···) any)      SYNTAX

The opt-> expression constructs a contract for an opt-lambda function. The first arguments are the required parameters, the second arguments are the optional parameters and the final argument is the result. The req-contracts expressions, the opt-contracts expressions, and the res-contract expressions can be any expression that evaluates to a contract value.

Each opt-> expression expands into case->.

The opt->* expression constructs a contract for an opt-lambda function. The only difference between opt-> and opt->* is that multiple return values are permitted with opt->* and they are specified in the last clause of an opt->* expression. A result of any means any value or any number of values may be returned, and the contract does not inhibit tail-recursion.

12.3  Lazy Data-structure Contracts

Typically, constracts on data structures can be written using flat contracts. For example, one might write a sorted list contract as a function that accepts a list and traverses it, ensuring that the elements are in order. Such contracts, however, can change the asymptotic running time of the program, since the contract may end up exploring more of a function's input than the function itself does. To circumvent this problem, the define-contract-struct form introduces contract combinators that are lazy that is, they only verify the contract holds for the portion of some data structure that is actually inspected. More precisely, a lazy data structure contract on a struct is not checked until a selector extracts a field of a struct.

The form

(define-contract-struct struct-name (field ...))

is like the corresponding define-struct, with two differences: it does not define field mutators and it does define two contract constructors: struct-name/c and struct-name/dc. The first is a procedure that accepts as many arguments as there are fields and returns a contract for struct values whose fields match the arguments. The second is a syntactic form that also produces contracts on the structs, but the contracts on later fields may depend on the values of earlier fields. It syntax is:

(struct-name/dc field-spec ...)

where each field-spec is one of the following two lines:

[field contract-expr]
[field (field ...) contract-expr]

In each case, the first field name specifies which field the contract applies to, and the fields must be specified in the same order as the original define-contract-struct. The first case is for when the contract on the field does not depend on the value of any other field. The second case is for when the contract on the field does depend on some other fields, and the field names in middle second indicate which fields it depends on. These dependencies can only be to fields that come earlier in the struct.

As an example consider this module:

(module product mzscheme
  (require (lib "contract.ss"))

  (define-contract-struct kons (hd tl))
  
  ;; sorted-list/gt : number -> contract
  ;; produces a contract that accepts
  ;; sorted kons-lists whose elements
  ;; are all greater than `num'.
  (define (sorted-list/gt num)
    (or/c null?
          (kons/dc [hd (>=/c num)]
                   [tl (hd) (sorted-list/gt hd)])))
  
  ;; product : kons-list -> number
  ;; computes the product of the values
  ;; in the list. if the list contains
  ;; zero, it avoids traversing the rest
  ;; of the list.
  (define (product l)
    (cond
      [(null? l) 1]
      [else
       (if (zero? (kons-hd l))
           0
           (* (kons-hd l) 
              (product (kons-tl l))))]))
  
  (provide kons? make-kons kons-hd kons-tl)
  (provide/contract [product (-> (sorted-list/gt -inf.0) number?)]))

It provides a single function, product whose contract indicates that it accepts sorted lists of numbers and produces numbers. Using an ordinary flat contract for sorted lists, the product function cannot avoid traversing having its entire argument be traversed, since the contract checker will traverse it before the function is called. As written above, however, when the product function aborts the traversal of the list, the contract checking also stops, since the kons/dc contract constructor generates a lazy contract.

12.4  Object and Class Contracts

This section describes contracts on classes and objects. Here is the basic shape of an object contract:

contract-expr ::== ···
 | (object-contract meth/field-spec ···)

meth/field-spec ::==
   (meth-name meth-contract)
 | (field field-name contract-expr)

meth-contract ::==
   (opt-> (required-contract-expr ···)
          (optional-contract-expr ···)
          any)
   (opt-> (required-contract-expr ···)
          (optional-contract-expr ···)
          result-contract-expr)
 | (opt->* (required-contract-expr ···)
           (optional-contract-expr ···)
           (result-contract-expr ···))
 | (case-> meth-arrow-contract ···)
 | meth-arrow-contract

meth-arrow-contract ::==
   (-> dom-contract-expr ··· rng-contract-expr)
 | (-> dom-contract-expr ··· (values rng-contract-expr ···))
 | (->* (dom-contract-expr ···) (rng-contract-expr ···))
 | (->* (dom-contract-expr ···) rest-arg-contract-expr (rng-contract-expr ···))
 | (->d dom-contract-expr ··· rng-contract-proc-expr)
 | (->d* (dom-contract-expr ···) rng-contract-proc-expr)
 | (->d* (dom-contract-expr ···) rest-contract-expr rng-contract-proc-expr)
 | (->r ((id expr) ···) expr)
 | (->r ((id expr) ···) id expr expr)
 | (->pp ((id expr) ···) pre-expr expr res-id post-expr)
 | (->pp ((id expr) ···) pre-expr any)
 | (->pp ((id expr) ···) pre-expr (values (id expr) ···) post-expr)
 | (->pp-rest ((id expr) ···) id expr pre-expr expr res-id post-expr)
 | (->pp-rest ((id expr) ···) id expr pre-expr any)
 | (->pp-rest ((id expr) ···) id expr pre-expr (values (id expr) ···) post-expr)

Each of the contracts for methods has the same semantics as the corresponding function contract (discussed above), but the syntax of the method contract must be written directly in the body of the object-contract (much like the way that methods in class definitions use the same syntax as regular function definitions, but cannot be arbitrary procedures).

The only exception is that the ->r, ->pp, and ->pp-rest contracts implicitly bind this to the object itself.

mixin-contract      CONTRACT

mixin-contract is a contract that recognizes mixins. It is a function contract. It guarantees that the input to the function is a class and the result of the function is a subclass of the input.

(make-mixin-contract class-or-interface ···)      CONTRACT

make-mixin-contract is a function that constructs mixins contracts. It accepts any number of classes and interfaces and returns a function contract. The function contract guarantees that the input to the function implements the interfaces and is derived from the classes and that the result of the function is a subclass of the input.

12.5  Attaching Contracts to Values

There are three special forms that attach contract specification to values: provide/contract, define/contract, and contract.

(provide/contract p/c-item ···)      SYNTAX

p/c-item is one of
  (struct identifier ((identifier contract-expr) ···))
  (struct (identifier identifier) ((identifier contract-expr) ···))
  (rename id id contract-expr)
  (id contract-expr)

A provide/contract form can only appear at the top-level of a module (see section 5 in PLT MzScheme: Language Manual). As with provide, each identifier is provided from the module. In addition, clients of the module must live up to the contract specified by contract-expr.

The provide/contract form treats modules as units of blame. The module that defines the provided variable is expected to meet the positive (co-variant) positions of the contract. Each module that imports the provided variable must obey the negative (contra-variant) positions of the contract.

Only uses of the contracted variable outside the module are checked. Inside the module, no contract checking occurs.

The rename form of a provide/contract exports the first variable (the internal name) with the name specified by the second variable (the external name).

The struct form of a provide/contract clause provides a structure definition. Each field has a contract that dictates the contents of the fields.

If the struct has a parent, the second struct form (above) must be used, with the first name referring to the struct itself and the second name referring to the parent struct. Unlike define-struct, however, all of the fields (and their contracts) must be listed. The contract on the fields that the sub-struct shares with its parent are only used in the contract for the sub-struct's maker, and the selector or mutators for the super-struct are not provided.

Note that the struct definition must come before the provide clause in the module's body.

(define/contract id contract-expr init-value-expr)      SYNTAX

The define/contract form attaches the contract contract-expr to init-value-expr and binds that to id.

The define/contract form treats individual definitions as units of blame. The definition itself is responsible for positive (co-variant) positions of the contract and each reference to id (including those in the initial value expression) must meet the negative positions of the contract.

Error messages with define/contract are not as clear as those provided by provide/contract because define/contract cannot detect the name of the definition where the reference to the defined variable occurs. Instead, it uses the source location of the reference to the variable as the name of that definition.

(contract contract-expr to-protect-expr positive-blame negative-blame)      SYNTAX

(contract contract-expr to-protect-expr positive-blame negative-blame contract-source)      SYNTAX

The contract special form is the primitive mechanism for attaching a contract to a value. Its purpose is as a target for the expansion of some higher-level contract specifying form.

The contract form has this shape:

(contract expr to-protect-expr positive-blame negative-blame contract-source)

The contract expression adds the contract specified by the first argument to the value in the second argument. The result of a contract expression is the result of the to-protect-expr expression, but with the contract specified by contract-expr enforced on to-protect-expr. The expressions positive-blame and negative-blame must be symbols indicating how to assign blame for positive and negative positions of the contract specified by contract-expr. Finally, contract-source, if specified, indicates where the contract was assumed. It must be a syntax object specifying the source location of the location where the contract was assumed. If the syntax object wraps a symbol, the symbol is used as the name of the primitive whose contract was assumed. If absent, it defaults to the source location of the contract expression.

12.6  Contract Utility

contract?      PREDICATE

The procedure contract? returns #t if its argument is a contract (ie, constructed with one of the combinators described in this section).

flat-contract?      PREDICATE

This predicate returns true when its argument is a contract that has been constructed with flat-contract (and thus is essentially just a predicate).

(flat-contract-predicate value)      SELECTOR

This function extracts the predicate from a flat contract.

(contract-first-order-passes? contract value)      PROCEDURE

Returns a boolean indicating if the first-order tests of contract pass for value.

If it returns #f, the contract is guaranteed not to hold for that value; if it returns #t, the contract may or may not hold. If the contract is a first-order contract, a result of #t guarantees that the contract holds.

(make-none/c sexp-name)      PROCEDURE

Makes a contract that accepts no values, and reports the name sexp-name when signaling a contract violation.

(contract-violation->string [violation-renderer])      PROCEDURE

This is a parameter that is used when constructing a contract violation error. Its value is procedure that accepts six arguments: the value that the contract applies to, a syntax object representing the source location where the contract was established, the names of the two parties to the contract (as symbols) where the first one is the guilty one, an sexpression representing the contract, and a message indicating the kind of violation. The procedure then returns a string that is put into the contract error message. Note that the value is often already included in the message that indicates the violation.

(recursive-contract contract)      SYNTAX

Unfortunately, the standard contract combinators (like ->, etc) evaluate their arguments eagerly, leading to either references to undefined variables or infinite loops, while building recursive contracts.

The recursive-contract form delays the evaluation of its argument until the contract is checked, making recursive contracts possible.