doc.txt

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