GBBopen is a new design based on the concepts that were explored in the UMass Generic Blackboard system and the commercial GBB product. It is not an updated version of the GBB product. Nevertheless, the non-graphical portion of most GBB applications can be migrated to GBBopen with minor effort.
GBBopen design decisions and syntax that diverge from those made for GBB are surveyed below. This list is not complete and new items may be added as the GBBopen Project moves forward. Comments are welcomed at comments@GBBopen.org.
- Rename some entities, including:
Original GBB Name Corresponding GBBopen Name count-units-of-class class-instances-count delete-unit delete-instance describe-blackboard-database describe-blackboard-repository get-unit find-instance-by-name filter-units filter-instances find-units find-instances linkf! link-setf make-unit make-instance map-units-of-class map-instances-of-class do-instances-of-class map-units-on-space-instances map-instances-on-space-instances do-instances-on-space-instances unit-deleted-p instance-deleted-p unit-dimension-value instance-dimension-value unit-name instance-name-of unit-space-instance-paths space-instances-of Rationale: Renaming presents an opportunity to add more consistency and CLOS uniformity to GBBopen entity names. Some of these entities have semantic differences from their GBB counterparts, so their use should also be reviewed during application migration. Some system unit-class and event-class names have also been renamed (and others eliminated, see below), again for consistency. Downside: A hassle for migrating existing GBB applications to GBBopen. Experienced GBB users will have to learn the new names.
- Change the default accessor-name generation from the traditional
Rationale: The GBB-style accessor names were introduced in the UMass Generic Blackboard System, which predated CLOS and was structure based. This naming convention was retained in GBB, primarily to keep the format of generated accessor names for structures and CLOS instances unified.
Embedding the originating class name in accessor functions exposes class inheritance throughout an application, which conflicts with the flexible nature of CLOS. One solution is to simply use the slot name as the accessor name, but this strategy can lead to unanticipated name collisions with other functions in Common Lisp and applications. The
accessor format avoids most name collisions (with the exception of
but it doesn't work well with some boolean-adjective slot names (such as
For these slots, excluding automatic accessor generation in favor of specifying
accessor names manually is recommended.
Downside: Slight potential for accessor-method overloading when using accessor names.
- Eliminate blackboard/space definitions and
Rationale: Separation of space definition from instantiation in GBB presented a significant conceptual hurdle to new users. Intended to simplify the instantiation of large, complex blackboard structures, the power of this separation was seldom needed. A more direct make/delete approach is easily understood, with similarity to directory creation/deletion in a hierarchical file system serving as a guide. User-supplied functions can be developed and used when instantiation complexity requires mapping complex “definitional” specifications into appropriate calls to make-space-instance. Downside: Minimal for most users.
- Space instances are unit instances.
Rationale: Numerous requests were made by GBB users to make space instances more like unit instances (with slots, links, etc.). Making space instances a subclass of standard-unit accomplishes this, reduces implementation complexity by sharing code with “regular” unit instances, and allows spaces to be used and subclassed in highly creative ways. Just as unit-instance classes have their own metaclass, standard-unit-class, space-instance classes have their own metaclass, space-instance-class, that is a subclass of the standard-unit-class metaclass. Downside: Space instances lose their special status. Syntactic-sugar entities (such as, make-space-instance and delete-space-instance) help to provide an illusion of greater distinction from “regular” unit instances.
Mapping over the instances of all unit classes now includes space instances, which may surprise some users. For example:
will delete all space instances as well as all unit instances.
(map-instances-of-class #'delete-instance 't)
- In define-unit-class, use a one-argument function
rather than GBB's evaluated path expression to compute the
initial-space-instances for a newly created unit instance. Also,
rename this class option as
Rationale: GBB used an evaluated
:pathsexpression to determine the initial space instances for a newly created unit instance. Often, this was a constant value and the GBB
:pathsexpression was simply a quoted path list. Computed initial space instances based on slot values of the newly created unit instance required the unwieldy definition of path-variable bindings and a backquoted
In GBBopen, the
value can be either one or more path literals or a one-argument function that is called with the newly created unit instance and must return zero or more space instances. The separation of constant and computed mechanisms makes both situations more natural and efficient.
Downside: Minor syntactic change for most users.
as be the default for non-extended unit-class specifications (instead of
Rationale: The default of causes extra work in find-instances and unit-instance-mapping operations when subclasses are traversed, can lead to surprises when using find-instance-by-name, and can encourage casual thinking of class relationships. Requiring
provides clear indication of when this extra search through subclasses is intended. Use of the
specification remains as a convenient abbreviation for
which is where the use of
occurs most often.
The same rationale holds for
as the default for non-extended event-class specifications. Again the
specification remains as a convenient abbreviation for
which is where the use of
occurs most often.
Downside: Users may forget when specifying a class subtree for a space instance via
a place of where
is often intended.
- Eliminate slot-initialization events.
Rationale: Initialization events for link and non-link slots were rarely used on their own. When changes to a specific slot were important, event functions were added for both the initialization and the update or link/unlink events for those slots. In GBBopen, a nonlink-slot-update-event or link-event is signaled in place of GBB's slot/link-initialization events. Downside: It's now harder to have a slot-update event function ignore nonlink-slot-update-events and link-events that are signaled during instance creation.
- Eliminate access (reader) events.
Rationale: These were part of the pre-CLOS UMass Generic Blackboard implementation and were provided to support on-demand computation of slot values. They were rarely used, add many additional event signatures, and slot-access activities can can be done via CLOS methods if needed. Downside: Minimal.
- Dimension names are not internalized as keyword
Rationale: Very few users relied upon (or were even aware of) GBB's internal conversion of dimension names to keyword symbols. Common Lisp package mechanisms (or simply using keyword names for dimensions) provide the same benefits explicitly, without relying on a hidden technique. Downside: Minimal.
- Support unbounded intervals and dimension
extents; for example:
Rationale: Although part of the original UMass Generic Blackboard system design, implementation of infinite (unbounded) dimension extents was postponed in the initial UMass release and never resurrected. Unbounded dimensions can be simulated with appropriately low/high bounds, but that approach is semantically ugly. Including unbounded intervals in GBBopen required little additional implementation effort. Downside: Some Common Lisp implementations require read-time evaluation (to be enabled when reading printed infinite values (a security risk), and there is no accepted convention for printing/reading infinite values among Common Lisp implementations. GBBopen addresses this issue by providing a dispatch macro
printed representation (such as
- Change find and filter-instance patterns from
infix to prefix style; eliminate keyword pattern operators.
Rationale: The partially-infix pattern syntax used in GBB was inconsistent with Common Lisp style and complex to parse by users and GBB. Using regular (non-keyword) symbols for pattern operators in the normal prefix position adds regularity (and Lisp-style beauty) to pattern elements. All keyword pattern operators, with the exception of
:all, have been eliminated. The pattern
tmatches all unit instances whose dimension values overlap the dimensional extent of at least one space instance in the space-instances being searched. The pattern
:allmatches every unit instance on a space instance being searched, regardless of dimensional overlap.
Downside: Patterns in existing code will require updating to the new syntax.
- Make pattern-match operators dimension-type specific.
Rationale: In GBB, some pattern operators (for example,
:exact) matched either ordered or enumerated dimension values, depending on the dimension type of the unit instance. Although intended for convenience, the lack of stronger dimension typing of patterns often resulted in unintended retrieval behavior and limited the retrieval optimizations available to GBB. By using strongly dimension-typed operators, retrieval patterns now have the same explicit dimensionality as unit and space instances, making the intended pattern semantics clear.
Downside: Patterns in existing code will require updating to the new operators. Patterns using the same operator over multiple dimension types will require restructuring.
- Change the :label dimension-value type to
:interval, and also support a new dimension-value type,
Rationale: The use of
:labelto indicate an enumerated-dimension value was always a bit confusing to newcomers;
:elementis a bit more intuitive. The change from
:intervalis more in keeping with mathematical terminology. Support for
:mixedallows a unit class to have values in a dimension that can be either a point or an interval (a useful extension).
Downside: Some dimension-value-type specifications will need renaming in existing code.