racket/collects/plai/doc.txt
Matthew Flatt 9ef0da0dc6 fixed plai docs
svn: r598
2005-08-16 02:11:48 +00:00

164 lines
6.9 KiB
Plaintext

The _Programming Languages: Application and Interpretations_ languages
are companion to the textbook of the same name.
In the language dialog box, you will find the four _PLAI_ language:
PLAI - Beginning Student
PLAI - Intermediate Student with lambda
PLAI - Advanced Student
PLAI - Pretty Big
This language sequence follows the same progression as the book "How
to Design Programs" (htdp). If you are learning Scheme with the book
while taking the class, the PLAI languages will provide the same
support as the HtDP languages. Namely, at each language level the
error messages you receive are explained in term of the constructs you
know so far, and are tailored to address the common errors done at that
level.
--- Syntactic forms ---------------------------------------------------
> (define-type ID (VARIANT-ID (FIELD-ID CONTRACT-EXPR) ...) ...)
Defines the datatype ID and a function ID? that returns true for
instances of the datatype, and false for any other value. Here, the
name ID? means the given name ID, with an added question mark.
For each VARIANT-ID, a constructor VARIANT-ID is defined. The
constructor takes as many arguments as the variant's FIELD-IDs, and
it returns an instance of this datatype. Each argument to the
constructor is checked by applying the contract produced by the
variant's CONTRACT-EXPR.
In the PLAI Beginner language, a CONTRACT-EXPR should be the name of
a predicate, i.e., a procedure of one argument that returns a
boolean. In higher language levels, a CONTRACT-EXPR can produce
anything that is allowed as a contract by MzLib's "contract.ss"
library (which includes predicate procedures).
An instance constructed by the VARIANT-ID can be deconstructed using
`type-case'. Also, for each FIELD-ID of a VARIANT-ID, `define-type'
provides VARIANT-ID-FIELD-ID to access each field in an instance of
each variant, and a predicate VARIANT-ID? to recognize instances of
the variant.
In PLAI Intermediate and later, `define-type' produces additional
contract-related bindings, and it also supports a generalization of
ID. See "Datatypes and Contracts" below.
> (type-case DATATYPE-ID EXPR (VARIANT-ID (FIELD-ID ...) RESULT-EXPR ...) ...)
> (type-case DATATYPE-ID EXPR (VARIANT-ID (FIELD-ID ...) RESULT-EXPR ...) ...
(else ELSE-EXPR ...))
Branches on the datatype instance produced by EXPR, which must be an
instance of the specified DATATYPE-ID (previously defined with
`define-type'). Each clause pattern automatically extract the values
stored in the fields of the structure. It binds the extracted values
them to the names FIELD-IDs in the order that the fields were
declared in the corresponding definition in the `define-type'.
The `type-case' form complains if you do not handle all the variants
in a datatype. You can use the `else' keyword as the last clause of
a `type-case' to create a catch-all clause. In that case, variants
which are not handled by the other clauses will trigger the
evaluation of the ELSE-EXPR.
If it should not be possible to reach the `else' clause according to
the logic of your program, your ELSE-EXPR should be a call to
`error', which will raise an exception. For example:
(type-case shape a-circle
[circle (c r) (* pi (sqr r))]
[else (error "expected a circle!")])
--- Datatypes and Contracts ------------------------------------------------
> (define-type (ID PARAM-ID ...) (VARIANT-ID (FIELD-ID CONTRACT-EXPR) ...) ...)
This form of `define-type' is supported only in the PLAI
Intermediate langauge and higher.
Each PARAM-ID stands for a contract parameter, and can
appear as a free variable in the CONTRACT-EXPRs. When VARIANT-ID is
used directly, then `any/c' is substituted for each PARAM-ID to
obtain the relevant field contracts. Using ID by itself after
`define-type' is the same as (ID) with no PARAM-IDs.
VARIANT-ID-of is bound to a constructor generator for each
VARIANT-ID. Given a contract for each PARAM-ID, it produces a
constructor whose field contracts are the CONTRACT-EXPRs with
PARAM-IDs replaced by the given contracts.
ID-of/c is bound to a contract generator. Given a contract for each
PARAM-ID, it produces a contract that corresponds to the union of
the variant contracts PARAM-IDs replaced by the given contracts in
the CONTRACT-EXPRs.
Finally, VARIANT-ID-of/c is bound to a contract generator for each
VARIANT-ID. Given a contract for each PARAM-ID, it produces a
constructor whose field contracts are the CONTRACT-EXPRs with
PARAM-IDs replaced by the given contracts.
--- Testing support ---------------------------------------------------
> (test result expected-value)
Compares the result of a test expression to the expected value, and
return a list of three elements: the first element is the symbol
'good (if the test passed) or 'bad (if the test failed), the second
element is the result, and the third element is the expected value.
> (test/pred result predicate)
Applies the predicate to the result, and return a list of three
elements: the first element is the symbol 'good (if the predicate
returned true), or 'bad (if the predicate returned false), the
second element is the result, and the third element is the expected
values.
> (test/exn (lambda () expression) expected-error-message)
Evaluates the expression expecting an exception. This is useful to
verify that your program correctly detects error conditions. If the
expression does not raise an exception, TEST/PRED returns the list:
(list 'bad result expected-error-message)
If the evaluation of the expression did throw an exception, TEST/PRED
will pattern match the error message against the
expected-error-message, and return 'bad if the error was not the
expected error. EXPECTED-ERROR-MESSAGE should be a few words from
the expected error message. For example:
(text/exn (lambda () (/ 3 0)) "by zero")
evaluates to:
(list 'good #(struct:exn) "by zero")
> (print-tests false|true|'good|'bad|'stop)
PRINT-TESTS controls printing of test by TEST, TEST/PRED and TEST/EXN.
You can pass one of five values to PRINT-TESTS:
false Test result are not printed, they are simply returned. The
results of tests evaluated at the top-level will be
printed by DrScheme in the interaction panel, as usual.
(this is the default)
true all test results are printed
'good only successful test results are printed
'bad only failed test results are printed
'stop testing will stops at the first test that fails, by throwing
an exn:test exception.
> (test-inexact-epsilon number)
Sets the precision used by TEST to check the correctness of inexact
numbers. By default, floating-point results are considered correct
if they fall within 0.01 from their the expected value.