1 PLAI Scheme
#lang plai | package: plai-lib |
PLAI Scheme is derived from the scheme language. In addition, it includes the define-type and type-case forms and testing support. Also, modules written in plai export every definition (unlike scheme).
1.1 Defining Types: define-type
syntax
(define-type type-id variant ...)
(define-type type-id #:immutable variant ...)
variant = (variant-id (field-id contract-expr) ...)
The value of each field is checked by its associated contract-expr. A contract-expr may be an arbitrary predicate or a contract.
If the #:immutable option is provided, the constructors create immutable structs. Otherwise, they can be mutated.
In addition to the constructors, a define-type expression also defines:
a predicate type-id? that returns true for instances of the datatype, and false for any other value,
for each variant, a predicate variant-id? that returns true when applied to a value of the same variant and false for any other value,
for each field of each variant, an accessor variant-id-field-id that returns the value of the field, and
unless the #:immutable option is provided, for each field of each variant, define-type also defines a mutator set-variant-id-field-id! that sets the value of the field.
1.2 Deconstructing Data Structures: type-case
syntax
(type-case datatype-id expr branch ...)
branch = (variant-id (field-id ...) result-expr ...) | (else result-expr ...)
If a branch is not specified for each variant, you may use an else branch to create a catch-all branch. An else branch must be the last branch in the sequence of branches. type-case signals a compile-time error if all variants are not covered and the else branch is missing. Similarly, type-case signals a compile-time error if an else branch is unreachable because a branch exists for all variants.
1.3 Testing Infrastructure
PLAI Scheme provides the following syntactic forms for testing.
syntax
(test result-expr expected-expr)
(good result-expr result-value expected-value location).
If they do not evaluate to the same value, the test prints
(bad result-expr result-value expected-value location).
If evaluating result-expr signals an error, the test prints
(exception result-expr exception-message <no-expected-value> location)
If evaluating expected-expr signals an error, the test prints
(pred-exception result-expr exception-message <no-expected-value> location)
If the printout begins with good, then it is printed to (current-output-port); otherwise it is printed to (current-error-port).
syntax
(test/pred result-expr pred?)
If evaluating pred? signals an error, the test prints
(pred-exception result-expr exception-message <no-expected-value> location)
The syntax of pred? is considered expected-value for the purposes of test reporting.
value
syntax
(test/exn result-expr error-message)
For example, the following test succeeds:
The error message is "/: division by zero", and "by zero" is a substring of the error message. However, the following test fails:
Although the expression raises an exception and the error string contains "by zero", since the error was not explicitly raised by user-written code, the test fails.
The evaluation of error-message is considered expected-value for the purposes of test reporting.
syntax
(test/regexp result-expr error-message-regexp)
The evaluation of error-message-regexp is considered expected-value for the purposes of test reporting.
1.3.1 Test Equality
1.3.2 Test Flags
procedure
(abridged-test-output [abridge?]) → void?
abridge? : boolean? = false
procedure
(plai-catch-test-exn [catch?]) → void?
catch? : boolean? = true
procedure
(halt-on-errors [halt?]) → void?
halt? : boolean? = true
procedure
(print-only-errors [print?]) → void?
print? : boolean? = true
procedure
(test-inexact-epsilon epsilon) → void?
epsilon : number?
procedure
(plai-ignore-exn-strings ignore?) → void?
ignore? : boolean?
syntax