#lang scribble/doc
@(require
scribble/manual
(for-label
scheme
"../hierarchy.ss"))
@title[#:tag "hierarchy" #:style '(toc)]{Ad-Hoc Hierarchies of Values}
@defmodule[(planet "hierarchy.ss" ("murphy" "multimethod.plt" 1 0))]{
This module provides support for ad-hoc hierarchies of values that can
be used by multimethods.
}
@defproc[(make-hierarchy) hierarchy?]{
Creates a new value hierarchy.
}
@defproc[(hierarchy? [v any/c]) boolean?]{
Determines whether the given value is a hierarchy.
}
@defthing[global-hierarchy (parameter/c hierarchy?)]{
The global default value hierarchy.
}
@defstruct[(exn:fail:hierarchy exn:fail)
([child any/c]
[parent any/c])
#:transparent]{
Exception type raised when an illegal modification to a hierarchy is
attempted.
}
@defproc[(parents [h hierarchy? (global-hierarchy)]
[v any/c])
hash?]{
Retrieves all direct parents of @scheme[v] registered in
@scheme[h].
Returns a hash table mapping all the parents to @scheme[#t].
}
@defproc[(ancestors [h hierarchy? (global-hierarchy)]
[v any/c])
hash?]{
A transitive version of @scheme[parents]. Retrieves all ancestors of
@scheme[v] registered in @scheme[h] or in the global default
hierarchy, if the single argument form is used.
Returns a hash table mapping all the ancestors to @scheme[#t].
}
@defproc[(descendants [h hierarchy? (global-hierarchy)]
[v any/c])
hash?]{
The counterpart of @scheme[ancestors]. Retrieves all descendants of
@scheme[v] registered in @scheme[h] or in the global default
hierarchy, if the single argument form is used.
Returns a hash table mapping all the ancestors to @scheme[#t].
}
@defproc[(derived? [h hierarchy? (global-hierarchy)]
[child any/c] [parent any/c])
boolean?]{
Checks whether @scheme[child] is a descendant of @scheme[parent]
using the scheme object system and the ad-hoc hierarchy @scheme[h]
or the global default hierarchy, if the two argument form is used.
This procedure first converts @scheme[child] and / or
@scheme[parent] into interfaces using @scheme[class->interface], if
they are classes. Then it returns @scheme[#t] iff any of the
following conditions, which are checked in order, is fulfilled:
@itemize{
@item{
@scheme[child] and @scheme[parent] are @scheme[equal?].
}
@item{
@scheme[parent] is an interface and @scheme[child] extends it.
}
@item{
@scheme[parent] is a registered ancestor of @scheme[child] in
the type hierarchy.
}
@item{
@scheme[child] is an interface and extends some other interface
that is a registered descendant of @scheme[parent] in the type
hierarchy.
}
@item{
@scheme[child] and @scheme[parent] both satisfy @scheme[dict?],
all keys from the @scheme[parent] are present in the
@scheme[child] and all values in the @scheme[child] are
@scheme[derived?] from the corresponding values in the
@scheme[parent].
}
}
}
@defproc*[(
[(derive [child any/c] [parent (not/c (or/c class? interface?))])
void?]
[(derive [h hierarchy?]
[child any/c] [parent (not/c (or/c class? interface?))])
hierarchy?]
)]{
Registers a direct @scheme[parent] of a @scheme[child] in a value
hierarchy. Updates the descendants and ancestors relations
accordingly.
Before the new relation is registered, the child is converted to an
interface using @scheme[class->interface], if it is a class. The
parent may not be a class or interface. Inheritance from classes or
interfaces must be done through the object system.
If the @scheme[child] already derives from the @scheme[parent] or if
the new inheritance relation would create a cycle, this procedure
signals an error.
If the two argument form of the procedure is used, the new modified
type hierarchy is based on the global hierarchy and replaces it. In
the three argument form, the new hierarchy is returned. The original
hierarchy object is never modified by this operation.
}