Struct
_Struct_
_struct_
This collection provides two files:
_datatype.ss_: algebraic datatype definitions
_hierarchy.ss_: hierarchical structure definitions
_class.ss_: utilities for the MzScheme class library
_struct.ss_ : utilities for structures
This library provides syntaxes for several important kinds of datatype
definitions, including algebraic datatypes and inheritance hierarchies, as well
as some utilities for datatypes based on structures. All the datatypes
implemented in this library are implemented as structures in order to be
compatible with the _match.ss_ and _plt-match.ss_ pattern-matching libraries.
======================================================================
datatype.ss
-----------
prop-list ::= ([prop-expr val-expr] ...)
type-clause ::= (type-name prop-list)
| type-name
variant-clause ::= [variant (field ...) prop-list]
| [variant (field ...)]
> (define-datatype type-clause variant-clause ...)
Declares a new algebraic datatype named by the `type-clause'
expression. Each variant is named by the `variant-clause' expression
with a list of zero or more fields named by the `field'
subexpressions. Analogous to `define-struct', `define-datatype' has
the side effect of defining constructors, selectors, and mutators for
each variant, with similar naming conventions.
If a list of custom struct type properties is provided for the root
type or variant sub-types, the corresponding struct types are declared
with the custom properties.
> (provide-datatype type)
Exports all constructors, selectors, and mutators for the given
algebraic datatype from the current module.
> (provide-datatype/contract type [variant (contract ...)] ...)
Exports all constructors, selectors, and mutators for the given
algebraic datatype from the current module, with contracts attached
to each field. The contracts are associated positionally with the
fields in the order in which the fields were declared (as well as the
order in which they must be provided to the constructors).
hierarchy.ss
------------
> (define-hierarchy (name (field ...)
(child (ch-field ...) etc ...)
...)) :: syntax
Defines a structure type hierarchy. The nesting of structure type inheritance
follows the nesting of the syntax tree.
> (provide-hierarchy name) :: syntax
Provides all structure definitions that were given in a _define-hierarchy_ form,
without attaching contracts to any of the fields.
> (provide-hierarchy/contract (name (contract ...)
(child (ch-contract ...) etc ...)
...)) :: syntax
Provides all structure definitions that were given in a _define-hierarchy_ form
with contracts attached to all of the fields. The structure of the syntax tree
must match the structure of the corresponding _define-hierarchy_ form exactly.
> (define-hierarchy/provide/contract (name ([field contract] ...)
(child ([ch-field ch-contract] ...) etc ...)
...)) :: syntax
Defines and provides a structure type hierarchy with contracts attached to each
of the fields.
> (without-hierarchy-contracts exp)
Convenience form for disregarding any contract information associated with
structure type hierarchies defined in the body of `exp' by forms from this
library. Since contracts tend to be large and slow to compile, this can be
useful for speeding up compilation (i.e., macro-expansion) times.
class.ss
--------
> (init-private init-private-decl ...) :: syntax
Defines local variables of a class with _init_ that are not exported as public
from the class. The by-name constructor argument names and internal variable
names are both the same and are specified by the identifier in each
init-private-decl.
> (init-private-field init-private-decl ...) :: syntax
Defines fields of a class with _init-field_ that are not exported as public from
the class. The by-name constructor argument names and internal field names are
both the same and are specified by the identifier in each init-private-decl.
init-private-decl is one of
(identifier default-value-expr)
identifier
> (method object-exp method-name)
Evaluates to a closure representing a first-class reference to an object's
method. This closure can then be used as an argument to a higher-order function
such as MAP or FOR-EACH.
> (define-method access (name . args) body0 body1 ...) :: syntax
Defines a method with the given access that can be used in ordinary method
application expressions or in a higher-order fashion as an argument. The
`access' expression must be one of the following keywords (bound in the
`class.ss' module):
public
override
augment
pubment
overment
augride
public-final
override-final
augment-final
Note that this form does NOT work for methods declared `private'. Attempts to
define private methods with `define-method' result in a syntax error.
> (% class-or-interface-expr object-access ...) :: match syntax
Extended form for `match.ss' or `plt-match.ss' in the standard mzscheme
library. This form tests a value to see if it is an instance of a class or
implementation of an interface (using `is-a?'), and if so, binds each variable
in the `object-access ...' sub-expressions.
object-access is one of
[x (method-name args ...)]
[x field-name]
field-name
The first case binds the variable `x' to the result of sending the `method-name'
message to the object being matched with the given arguments.
The second case binds the variable `x' to the result of extracting the
`field-name' field from the object being matched.
The third case binds the variable `field-name' to the result of extracting the
`field-name' field from the object being matched.
If any object access fails, it raises the relevant exception from the `class.ss'
library, as opposed to simply failing to match.
struct.ss
---------
> (define-struct/opt name (field ... (field default) ...) [inspector])
> (define-struct/opt (name parent) (field ... (field default) ...) [inspector])
This form is identical to the _define-struct_ form, except it allows the
constructor to contain optional arguments just like procedures defined using
_opt-lambda_ (see the documentation for _etc.ss_ for details).
EXAMPLES -------------------------------------------------------------
;; 1. Algebraic datatypes:
(define-datatype Term
[Var (name)]
[Abs (var body)]
[App (rator rand)])
(provide-datatype/contract Term
[Var (symbol?)]
[Abs (symbol? Term?)]
[App (Term? Term?)])
(define Delta
(make-Abs 'x
(make-App (make-Var 'x)
(make-Var 'x))))
(define Omega
(make-App Delta Delta))
;; 2. Algebraic datatypes with custom write properties (OO):
(define (write-var t port write?)
(fprintf port "~a" (Var-name t)))
(define (write-abs t port write?)
(fprintf port "\\~a.~a" (Abs-var t) (Abs-body t)))
(define (write-app t port write?)
(fprintf port "(~a ~a)" (App-rator t) (App-rand t)))
(define-datatype Term
[Var (name) ([prop:custom-write write-var])]
[Abs (var body) ([prop:custom-write write-abs])]
[App (rator rand) ([prop:custom-write write-app])])
;; Sample interaction (using above definitions):
> Omega
(\x.(x x) \x.(x x))
;; 3. Algebraic datatypes with custom write properties (FP):
(define (write-term t port write?)
(cond
[(Var? t) (fprintf port "~a" (Var-name t))]
[(Abs? t) (fprintf port "\\~a.~a" (Abs-var t) (Abs-body t))]
[(App? t) (fprintf port "(~a ~a)" (App-rator t) (App-rand t))]))
(define-datatype (Term ([prop:custom-write write-term]))
[Var (name)]
[Abs (var body)]
[App (rator rand)])
;; Note that we can't use match.ss here, because `write-term'
;; has to be defined lexically before the datatype is defined.
;; 4. Type hierarchies:
(define-hierarchy/provide/contract
(error ([message string?])
(error:contract ([label symbol?] [guilty-party string?])
(error:contract:arity ([expected integer?] [actual integer?])))
(error:io ()
(error:io:eof ()))))
;; 5. Structs with optional arguments:
(define-struct/opt file (path [public? #f] [directory? #f]))
(define my-file (make-file "/dev/null"))
(file-public? my-file) ; => #f
(file-directory? my-file) ; => #f