fixed plai docs

svn: r598
This commit is contained in:
Matthew Flatt 2005-08-16 02:11:48 +00:00
parent 665706fd66
commit 9ef0da0dc6

View File

@ -1,6 +1,6 @@
The _Programming Languages: Application and Interpretations_ languages
are companion to the textbook, and to the _CS173_ class at Brown university.
are companion to the textbook of the same name.
In the language dialog box, you will find the four _PLAI_ language:
@ -12,66 +12,95 @@ In the language dialog box, you will find the four _PLAI_ language:
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
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.
The PLAI languages provide constructs that are essential to the
coding style prescribed in the class:
--- Syntactic forms ---------------------------------------------------
- Lists are only for holding multiple elements of the same type. Use
DEFINE-TYPE and TYPE-CASE to group elements of different types.
- All functions must have tests that exercise non-trivial cases. Use
TEST, TEST/PRED and TEST/EXN (below) to create a persistent
collection of tests for your code.
> (define-type id (variant-id (field-id predicate-expr) ...) ...)
> (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-ID's, and
returns and instance of this datatype. Each argument to the
constructor is checked by applying the function produced by the
variant's PREDICATE-EXPR. DEFINE-TYPE can also use contracts as
defined in (lib "contract.ss"), instead of predicates.
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.
The instance constructed by the VARIANT-ID can be deconstructed
using TYPE-CASE. Also, for each VARIANT-ID, DEFINE-TYPE also provide
functions that accesses the individual fields, and a predicate
VARIANT-ID? which recognizes instances of that particular variant.
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.
> (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 ...))
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.
Branches on the datatype instance produced by EXPR, which must be
an instance of the specified DATATYPE-ID (previously defined with
DEFINE-DATATYPE). 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-datatype.
> (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 ...))
TYPE-CASE will complains if you do not handle all the variants in a
datatype. You can use the ELSE keyword as the last clause of a CASES
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.
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'.
If it should not be possible to reach the else clause according to
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:
`error', which will raise an exception. For example:
(cases shape a-circle
[circle (c r) (* pi (sqr r))]
[else (error "expected a circle!")])
(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)