Error Handling

This chapter describes how error handling is performed in the PLT Scheme Science Collection and its error handling conventions.

3.1  Contracts

In PLT Scheme, a contract defines and enforces the interface to (and from) a function. Contracts are defined in Chapter 13: contract.ss: Contracts in the PLT MzLib: Libraries Manual[4].

The PLT Scheme Science Collection uses contracts to define and enforce the interfaces for all of the functions provided by the modules in the collection. This ensures that all calls to these functions are checked for the proper number and type of arguments (and results) as well as range checking and inter-argument constraints where practical.

All of the function descriptions in this manual include a specification of the contract for the function.

The following examples show some of the different contract specifications for functions and how to interpret them. All of these examples are from the statistics.ss file.

3.1.1  Fixed Number of Arguments with a Single Result

Example: mean from the statistics.ss file.

Function:
(mean data)

Contract:

(-> (vectorof real?) real?)

The contract specifies a function with one argument, which must match the contract (vectorof real?), and returns a single value, which must match the contract real?.

> (require (planet "statistics.ss" ("williams" "science.plt")))
> (mean #(1 2 3 4))
2.5
> (mean #(1 2 3 'a))
6:3: top-level broke the contract (-> (vectorof real?) real?) it had
with (planet "statistics.ss" ("williams" "science.plt")) on mean;
expected <(vectorof real?)>, given: #4(1 2 3 'a)

3.1.2  Multiple Lambda Forms (case-lambda)

Example: variance from the statistics.ss file.

Function:
(variance data mu)

Contract:

(case->
   (-> (vectorof real?) real? (>=/c 0.0))
   (-> (vectorof real?) (>=/c 0.0)))

The contract specifies multiple lambda forms using case->. The first case specifies a function with two arguments, which must match the contracts (vectorof real?) and real?, and returns a single value, which must match the contract (>=/c 0.0). The second case specifies a function with a single arguemnt, which must match the contract (vectorof real?), and returns a single value, which must match the contract (>=/c 0.0).

> (require (planet "statistics.ss" ("williams" "science.plt")))
> (variance #(1 2 3 4))
1.6666666666666665
> (variance #(1 2 3 4) 2.5)
1.6666666666666665
> (variance #(1 2 3 4) 'a)
8:3: top-level broke the contract 
  (case->
    (-> (vectorof real?) real? (>=/c 0.0))
    (-> (vectorof real?) (>=/c 0.0)))
it had with (planet "statistics.ss" ("williams" "science.plt"))
on variance; expected <real?>, given: a

3.1.3  Interparameter Constraints

Example: weighted-mean from the statistics.ss file.

Function:
(weighted-mean w data)

Contract:

(->r ((w (vectorof real?))
      (data (and/c (vectorof real?)
                   (lambda (x)
                     (= (vector-length w)
                        (vector-length data))))))
      real?)

The contract specifies a function that takes two arguments: the first argument must be a vector of real numbers and the second must be a vector of real number whose length is the same as the first argument; and the function returns one real result.

> (require (planet "statistics.ss" ("williams" "science.plt")))
> (weighted-mean #(1 2 3 4) #(4 3 2 1))
2.0
> (weighted-mean #(1 2 3 4) #(4 3 2))
6:3: top-level broke the contract 
  (->r ((w ...) (data ...)) ...)
it had with (planet "statistics.ss" ("williams" "science.plt"))
on weighted-mean; expected <(and/c (vectorof real?)
...\0\statistics.ss:119:23)>, given: #3(4 3 2)

3.2  Infinities and Not-a-Number

PLT Scheme provides +inf.0 (positive infinity), -inf.0 (negative infinity), +nan.0 (not-a-number), and -nan.0 (same as +nan.0). In general, these are contagious and are passed as the result in subsequent numerical computations. However, operations with infinities and zero (both exact and inexact) can give non-intuitive results. For example:

(Note that some of these may break naïve algorithms.)

The PLT Scheme Science Collection uses +inf.0 to represent overflow and -inf.0 to represent underflow in numerical computations. This is used in cases where the arguments to the function are within the range of the function, but the result is too large or too small to be represented. For example, (gamma 200.0) --> +inf.0.

The PLT Scheme Science Collection uses +nan.0 for domain errors - where the arguments match the contract, but the value cannot be computed. For example, (gamma 0.0) --> +nan.0.

3.3  Exceptions

In PLT Scheme, an exception is a change in control flow, typically as the result of an error. Exceptions are defined in Chapter 6 Exceptions and Control Flow in the PLT MzScheme Language Manual[3].

The PLT Scheme Science Collection may raise exceptions for errors other than underflow, overflow, and domain errors. Also, underlying procedures and/or modules used by the science collection may raise exceptions as may errors in the implementation.