λ

The GEB Manual

Table of Contents

[in package GEB-DOCS/DOCS]

Welcome to the GEB project.

λ

1 Links

Here is the official repository

and HTML documentation for the latest version.

Maintainers: please read the maintainers guide

λ

1.1 code coverage

For test coverage it can be found at the following links:

SBCL test coverage

CCL test coverage: current under maintenance


Note that due to #34 CCL tests are not currently displaying


I recommend reading the CCL code coverage version, as it has proper tags.

Currently they are manually generated, and thus for a more accurate assessment see GEB-TEST:CODE-COVERAGE

λ

2 Getting Started

Welcome to the GEB Project!

λ

2.1 installation

This project uses common lisp, so a few dependencies are needed to get around the code-base and start hacking. Namely:

  1. lisp with quicklisp.

  2. Emacs along with one of the following:

λ

2.2 loading

Now that we have an environment setup, we can load the project, this can be done in a few steps.

  1. Open the REPL (sbcl (terminal), M-x sly, M-x swank)

    • For the terminal, this is just calling the common lisp implementation from the terminal.

      user@system:geb-directory % sbcl.

    • For Emacs, this is simply calling either M-x sly or M-x slime if you are using either sly or slime

  2. From Emacs: open geb.asd and press C-ck (sly-compile-and-load-file, or swank-compile-and-load-file if you are using swank).

Now that we have the file open, we can now load the system by writing:

;; only necessary for the first time!
(ql:quickload :geb/documentation)

;; if you want to load it in the future
(asdf:load-system :geb/documentation)

;; if you want to load the codbase and run tests at the same time
(asdf:test-system :geb/documentation)

;; if you want to run the tests once the system is loaded!
(geb-test:run-tests)

λ

2.3 Geb as a binary

[in package GEB.ENTRY]

The standard way to use geb currently is by loading the code into one's lisp environment

(ql:quickload :geb)

However, one may be interested in running geb in some sort of compilation process, that is why we also give out a binary for people to use

An example use of this binary is as follows

mariari@Gensokyo % ./geb.image -i "foo.lisp" -e "geb.lambda.main::*entry*" -l -p -o "foo.pir"

mariari@Gensokyo % cat foo.pir
def entry x1 = {
  (x1)
};%
mariari@Gensokyo % ./geb.image -i "foo.lisp" -e "geb.lambda.main::*entry*" -l -p
def *entry* x {
  0
}

mariari@Gensokyo % ./geb.image -h
  -i --input                      string   Input geb file location
  -e --entry-point                string   The function to run, should be fully qualified I.E. geb::my-main
  -l --stlc                       boolean  Use the simply typed lambda calculus frontend
  -o --output                     string   Save the output to a file rather than printing
  -v --version                    boolean  Prints the current version of the compiler
  -p --vampir                     string   Return a vamp-ir expression
  -h -? --help                    boolean  The current help message

mariari@Gensokyo % ./geb.image -v
0.3.2

starting from a file foo.lisp that has

any valid lambda form. Good examples can be found at the following section:

The Simply Typed Lambda Calculus model

with the term bound to some global variable

(in-package :geb.lambda.main)

(defparameter *entry*
  (lamb (list (coprod so1 so1))
        (index 0)))

inside of it.

The command needs an entry-point (-e or --entry-point), as we are simply call LOAD on the given file, and need to know what to translate.

from STLC, we expect the form to be wrapped in the GEB.LAMBDA.SPEC.TYPED which takes both the type and the value to properly have enough context to evaluate.

It is advised to bind this to a parameter like in our example as -e expects a symbol.

the -l flag means that we are not expecting a geb term, but rather a lambda frontend term, this is to simply notify us to compile it as a lambda term rather than a geb term. In time this will go away

λ

3 Glossary

λ

4 Original Efforts

Originally GEB started off as an Idris codebase written by the designer and creator of GEB, Terence Rokop, However further efforts spawned for even further formal verification by Artem Gureev. Due to this, we have plenty of code not in Common Lisp that ought to be a good read.

λ

4.1 Geb's Idris Code

The Idris folder can be found in the geb-idris folder provided in the codebase

At the time of this document, there is over 16k lines of Idris code written. This serves as the bulk of the POC that is GEB and is a treasure trove of interesting information surrounding category theory.

λ

4.2 Geb's Agda Code

The Agda folder can be found in the geb-agda folder provided in the codebase

The Agda codebase serves as a great place to view formally verified properties about the GEB project. Although Geb's Idris Code is written in a dependently typed language, it serves as reference example of GEB, while Geb's Agda Code serves as the mathematical formalism proving various conjectures about GEB

λ

5 Categorical Model

Geb is organizing programming language concepts (and entities!) using category theory, originally developed by mathematicians, but very much alive in programming language theory. Let us look at a simple well-known example: the category of sets and functions. It is the bread and butter example: sets $A,B,C,…$ play the role of objects, functions are arrows between objects $A—f→B$, and the latter compose as functions do, such that every path of matching functions $$A—f→B—g→C—h→D$$ composes to a corresponding composite function $$A—f;g;h→D$$ (or $h∘g∘f$ if you prefer) and we enjoy the luxury of not having to worry about the order in which we compose; for the sake of completeness, there are identify functions $A —\mathrm{id}_A→ A$ on each set $A$, serving as identities (which correspond to the composite of the empty path on an object). Sets and functions together form a category—based on function composition; thus, let's call this category sets-'n'-functions. This example, even “restricted” to finite sets-'n'-functions, will permeate through Geb.

One of the first lessons (in any introduction to category theory) about sets-'n'-functions is the characterization of products and disjoint sums of sets in terms of functions alone, i.e., without ever talking about elements of sets. Products and co-products are the simplest examples of universal constructions. One of the first surprises follows suit when we generalize functions to partial functions, relations, or even multi-relations: we obtain very different categories! For example, in the category sets-'n'-relations, the disjoint union of sets features as both a product and a co-product, as a categorical construction.

Do not fear! The usual definition of products in terms of elements of sets are absolutely compatible with the universal construction in sets-'n'-functions. However we gain the possibility to compare the “result” of the universal constructions in sets-'n'-functions with the one in sets-'n'-relations (as both actually do have products).

for the purposes of Geb, many things can be expressed in analogy to the category of sets-'n'-functions; thus a solid understanding of the latter will be quite useful. In particular, we shall rely on the following universal constructions:

  1. The construction of binary products $A × B$ of sets $A,B$, and the empty product $mathsf{1}$.

  2. The construction of “function spaces” $B^A$ of sets $A,B$, called exponentials, i.e., collections of functions between pairs of sets.

  3. The so-called currying of functions, $C^{(B^A)} cong C^{(A × B)}$, such that providing several arguments to a function can done either simultaneously, or in sequence.

  4. The construction of sums (a.k.a. co-products) $A + B$ of sets $A,B$, corresponding to forming disjoint unions of sets; the empty sum is $varnothing$.

Product, sums and exponentials are the (almost) complete tool chest for writing polynomial expressions, e.g., $$Ax^{sf 2} +x^{sf 1} - Dx^{sf 0}.$$ (We need these later to define “algebraic data types”.) In the above expression, we have sets instead of numbers/constants where $ mathsf{2} = lbrace 1, 2 rbrace$, $ mathsf{1} = lbrace 1 rbrace$, $ mathsf{0} = lbrace rbrace = varnothing$, and $A$ and $B$ are arbitrary (finite) sets. We are only missing a counterpart for the variable! Raising an arbitrary set to “the power” of a constant set happens to have a very natural counterpart: the central actor of the most-well known fundamental result about categories, which generalizes Cayley's Theorem, i.e., the Yoneda embedding.

If you are familiar with the latter, buckle up and jump to Poly in Sets. Have a look at our streamlined account of The Yoneda Lemma if you are familiar with Cartesian closed categories, or take it slow and read up on the background in one of the classic or popular textbooks. Tastes tend to vary. However, Benjamin Pierce's Basic Category Theory for Computer Scientists deserves being pointed out as it is very amenable and covers the background we need in 60 short pages.

λ

5.1 Morphisms

λ

5.2 Objects

λ

5.3 The Yoneda Lemma

λ

5.4 Poly in Sets

λ

6 Project Idioms and Conventions

The Geb Project is written in Common Lisp, which means the authors have a great choice in freedom in how the project is laid out and operates. In particular the style of Common Lisp here is a functional style with some OO idioms in the style of Smalltalk.

The subsections will outline many idioms that can be found throughout the codebase.

λ

6.1 Spec Files, Main Files and Project Layout

[in package GEB.SPECS]

The codebase is split between many files. Each folder can be seen as a different idea within geb itself! Thus the poly has packages revolving around polynomials, the geb folder has packages regarding the main types of geb Subst Obj and Subst Morph, etc etc.

The general layout quirk of the codebase is that packages like geb.package.spec defines the specification for the base types for any category we wish to model, and these reside in the specs folder not in the folder that talks about the packages of those types. This is due to loading order issues, we thus load the specs packages before each of their surrounding packages, so that each package can built off the last. Further, packages like geb.package.main define out most of the functionality of the package to be used by other packages in geb.package, then all of these are reexported out in the geb.package package

Further to make working with each package of an idea is easy, we have the main package of the folder (typically named the same as the folder name) reexport most important components so if one wants to work with the fully fledged versions of the package they can simply without having to import too many packages at once.

For example, the geb.poly.spec defines out the types and data structures of the Polynomial Types, this is then rexported in geb.poly, giving the module geb.poly a convenient interface for all functions that operate on geb.poly.

λ

6.2 Open Types versus Closed Types

closed type's and open type's both have their perspective tradeoff of openness versus exhaustiveness (see the linked articles for more on that). Due to this, they both have their own favorable applications. I would argue that a closed ADT type is great tool for looking at a function mathematically and treating the object as a whole rather than piecemeal. Whereas a more open extension is great for thinking about how a particular object/case behaves. They are different mindsets for different styles of code.

In the geb project, we have chosen to accept both styles, and allow both to coexist in the same setting. We have done this with a two part idiom.

(deftype substobj ()
  `(or alias prod coprod so0 so1))

(defclass <substobj> (direct-pointwise-mixin) ())

(defclass so0 (<substobj>) ...)

(defclass prod (<substobj>) ...)

The closed type is GEB:SUBSTOBJ, filling and defining every structure it knows about. This is a fixed idea that a programmer may statically update and get exhaustive warnings about. Whereas GEB:<SUBSTOBJ> is the open interface for the type. Thus we can view GEB:<SUBSTOBJ> as the general idea of a GEB:SUBSTOBJ. Before delving into how we combine these methods, let us look at two other benefits given by GEB:<SUBSTOBJ>

  1. We can put all the Mixins into the superclass to enforce that any type that extends it has the extended behaviors we wish. This is a great way to generically enhance the capabilities of the type without operating on it directly.

  2. We can dispatch on GEB:<SUBSTOBJ> since DEFMETHOD only works on Common Lisp Object System (CLOS) types and not generic types in CL.

Methods for closed and open types

With these pieces in play let us explore how we write a method in a way that is conducive to open and closed code.

(in-package :geb)

(defgeneric to-poly (morphism))

(defmethod to-poly ((obj <substmorph>))
  (typecase-of substmorph obj
    (alias        ...)
    (substobj     (error "Impossible")
    (init          0)
    (terminal      0)
    (inject-left   poly:ident)
    (inject-right  ...)
    (comp          ...)
    (case          ...)
    (pair          ...)
    (project-right ...)
    (project-left  ...)
    (distribute    ...)
    (otherwise (subclass-responsibility obj))))

(defmethod to-poly ((obj <substobj>))
  (declare (ignore obj))
  poly:ident)

In this piece of code we can notice a few things:

  1. We case on GEB:SUBSTMORPH exhaustively

  2. We cannot hit the GEB:<SUBSTOBJ> case due to method dispatch

  3. We have this GEB.UTILS:SUBCLASS-RESPONSIBILITY function getting called.

  4. We can write further methods extending the function to other subtypes.

Thus the GEB.COMMON:TO-POLY function is written in such a way that it supports a closed definition and open extensions, with GEB.UTILS:SUBCLASS-RESPONSIBILITY serving to be called if an extension a user wrote has no handling of this method.

Code can also be naturally written in a more open way as well, by simply running methods on each class instead.

Potential Drawback and Fixes

One nasty drawback is that we can't guarantee the method exists. In java this can easily be done with interfaces and then enforcing they are fulfilled. Sadly CL has no such equivalent. However, this is all easily implementable. If this ever becomes a major problem, it is trivial to implement this by registering the subclasses, and the perspective methods, and scouring the image for instance methods, and computing if any parent class that isn't the one calling responsibility fulfills it. Thus, in practice, you should be able to ask the system if any particular extension fulfills what extension sets that the base object has and give CI errors if they are not fulfilled, thus enforcing closed behavior when warranted.

λ

6.3 ≺Types≻

These refer to the open type variant to a closed type. Thus when one sees a type like GEB: it is the open version of GEB:SUBSTOBJ. Read Open Types versus Closed Types for information on how to use them.

λ

7 The Geb Model

[in package GEB]

Everything here relates directly to the underlying machinery of GEB, or to abstractions that help extend it.

λ

7.1 The Categorical Interface

[in package GEB.MIXINS]

This covers the main Categorical interface required to be used and contained in various data structures

λ

7.2 Geneircs

[in package GEB.GENERICS]

These functions represent the generic functions that can be run on many parts of the compiler, they are typically rexported on any package that implements the given generic function.

You can view their documentation in their respective API sections.

The main documentation for the functionality is given here, with examples often given in the specific methods

λ

7.3 Core Category

[in package GEB.SPEC]

The underlying category of GEB. With Subst Obj covering the shapes and forms (GEB-DOCS/DOCS:@OBJECTS) of data while Subst Morph deals with concrete GEB-DOCS/DOCS:@MORPHISMS within the category.

From this category, most abstractions will be made, with SUBSTOBJ serving as a concrete type layout, with SUBSTMORPH serving as the morphisms between different SUBSTOBJ types. This category is equivalent to finset.

A good example of this category at work can be found within the Booleans section.

λ

7.3.1 Subst Obj

This section covers the objects of the SUBSTMORPH category. Note that SUBSTOBJ refers to the closed type, whereas <SUBSTOBJ> refers to the open type that allows for user extension.

SUBSTOBJ type is not a constructor itself, instead it's best viewed as the sum type, with the types below forming the constructors for the term. In ML we would write it similarly to:

type substobj = so0
              | so1
              | prod
              | coprod

The Accessors specific to Subst Obj

λ

7.3.2 Subst Morph

The overarching types that categorizes the SUBSTMORPH category. Note that SUBSTMORPH refers to the closed type, whereas <SUBSTMORPH> refers to the open type that allows for user extension.

SUBSTMORPH type is not a constructor itself, instead it's best viewed as the sum type, with the types below forming the constructors for the term. In ML we would write it similarly to:

type substmorph = comp
                | substobj
                | case
                | init
                | terminal
                | pair
                | distribute
                | inject-left
                | inject-right
                | project-left
                | project-right

Note that an instance of SUBSTOBJ, acts like the identity morphism to the layout specified by the given SUBSTOBJ. Thus we can view this as automatically lifting a SUBSTOBJ into a SUBSTMORPH

The Accessors specific to Subst Morph

λ

7.3.3 Realized Subst Objs

This section covers the REALIZED-OBJECT type. This represents a realized SUBSTOBJ term.

The REALIZED-OBJECT is not a real constructor but rather a sum type for the following type

(deftype realized-object () `(or left right list so1 so0))

In ML we would have written something like

type realized-object = so0
                     | so1
                     | list
                     | left
                     | right

λ

7.4 Accessors

[in package GEB.UTILS]

These functions are generic lenses of the GEB codebase. If a class is defined, where the names are not known, then these accessors are likely to be used. They may even augment existing classes.

λ

7.5 Constructors

[in package GEB.SPEC]

The API for creating GEB terms. All the functions and variables here relate to instantiating a term

More Ergonomic API variants for *SO0* and *SO1*

λ

7.6 API

Various forms and structures built on-top of Core Category

λ

7.6.1 Booleans

[in package GEB-BOOL]

Here we define out the idea of a boolean. It comes naturally from the concept of coproducts. In ML they often define a boolean like

data Bool = False | True

We likewise define it with coproducts

(def bool (coprod so1 so1))

(def true  (->right so1 so1))
(def false (->left  so1 so1))

The functions given work on this.

λ

7.6.2 Lists

[in package GEB-LIST]

Here we define out the idea of a List. It comes naturally from the concept of coproducts. Since we lack polymorphism this list is concrete over GEB-BOOL:@GEB-BOOL In ML syntax it looks like

data List = Nil | Cons Bool List

We likewise define it with coproducts, with the recursive type being opaque

(defparameter *nil* (so1))

(defparameter *cons-type* (reference 'cons))

(defparameter *canonical-cons-type*
  (opaque 'cons
          (prod geb-bool:bool *cons-type*)))

(defparameter *list*
  (coprod *nil* *cons-type*))

The functions given work on this.

λ

7.6.3 Translation Functions

[in package GEB.TRANS]

These cover various conversions from Subst Morph and Subst Obj into other categorical data structures.

λ

7.6.4 Utility

[in package GEB.MAIN]

Various utility functions ontop of Core Category

These utilities are ontop of CAT-OBJ

λ

7.7 Examples

PLACEHOLDER: TO SHOW OTHERS HOW EXAMPLEs WORK

Let's see the transcript of a real session of someone working with GEB:

(values (princ :hello) (list 1 2))
.. HELLO
=> :HELLO
=> (1 2)

(+ 1 2 3 4)
=> 10

λ

8 Extension Sets for Categories

[in package GEB.EXTENSION.SPEC]

This package contains many extensions one may see over the codebase.

Each extension adds an unique feature to the categories they are extending. To learn more, read about the individual extension you are interested in.

Common Sub expressions represent repeat logic that can be found throughout any piece of code

The Opaque extension lets users write categorical objects and morphisms where their implementation hide the specifics of what types they are operating over

The Natural Object/Morphism extension allows to expand the core Geb category with additional constructors standing in for bt-sequence representation of natural numbers along with basic operation relating to those.

λ

9 The GEB GUI

[in package GEB-GUI]

This section covers the suite of tools that help visualize geb objects and make the system nice to work with

λ

9.1 Visualizer

The GEB visualizer deals with visualizing any objects found in the Core Category

if the visualizer gets a Subst Morph, then it will show how the GEB:SUBSTMORPH changes any incoming term.

if the visualizer gets a Subst Obj, then it shows the data layout of the term, showing what kind of data

λ

9.1.1 Aiding the Visualizer

One can aid the visualization process a bit, this can be done by simply placing ALIAS around the object, this will place it in a box with a name to better identify it in the graphing procedure.

λ

9.2 Export Visualizer

This works like the normal visualizer except it exports it to a file to be used by other projects or perhaps in papers

λ

9.3 The GEB Graphizer

[in package GEB-GUI.GRAPHING]

This section covers the GEB Graph representation

λ

9.3.1 The GEB Graphizer Core

[in package GEB-GUI.CORE]

This section covers the graphing procedure in order to turn a GEB object into a format for a graphing backend.

The core types that facilittate the functionality

λ

9.3.2 The GEB Graphizer Passes

[in package GEB-GUI.GRAPHING.PASSES]

This changes how the graph is visualized, simplifying the graph in ways that are intuitive to the user

λ

10 Seqn Specification

[in package GEB.SEQN]

This covers a GEB view of multibit sequences. In particular this type will be used in translating GEB's view of multibit sequences into Vampir

λ

10.1 Seqn Types

[in package GEB.SEQN.SPEC]

λ

10.2 Seqn Constructors

[in package GEB.SEQN.SPEC]

Every accessor for each of the classes making up seqn

λ

10.3 seqn api

[in package GEB.SEQN.MAIN]

this covers the seqn api

λ

10.4 Seqn Transformations

[in package GEB.SEQN.TRANS]

This covers transformation functions from

λ

11 Bits (Boolean Circuit) Specification

[in package GEB.BITC]

This covers a GEB view of Boolean Circuits. In particular this type will be used in translating GEB's view of Boolean Circuits into Vampir

λ

11.1 Bits Types

[in package GEB.BITC.SPEC]

This section covers the types of things one can find in the BITs(0 1) constructors

λ

11.2 Bits (Boolean Circuit) Constructors

[in package GEB.BITC.SPEC]

Every accessor for each of the CLASS's found here are from Accessors

λ

11.3 Bits (Boolean Circuit) API

[in package GEB.BITC.MAIN]

This covers the Bits (Boolean Circuit) API

λ

11.4 Bits (Boolean Circuit) Transformations

[in package GEB.BITC.TRANS]

This covers transformation functions from

λ

12 Polynomial Specification

[in package GEB.POLY]

This covers a GEB view of Polynomials. In particular this type will be used in translating GEB's view of Polynomials into Vampir

λ

12.1 Polynomial Types

[in package GEB.POLY.SPEC]

This section covers the types of things one can find in the POLY constructors

λ

12.2 Polynomial API

[in package GEB.POLY.MAIN]

This covers the polynomial API

λ

12.3 Polynomial Constructors

[in package GEB.POLY.SPEC]

Every accessor for each of the CLASS's found here are from Accessors

λ

12.4 Polynomial Transformations

[in package GEB.POLY.TRANS]

This covers transformation functions from

λ

13 The Simply Typed Lambda Calculus model

[in package GEB.LAMBDA]

This covers GEB's view on simply typed lambda calculus

This serves as a useful frontend for those wishing to write a compiler to GEB and do not wish to target the categorical model.

If one is targeting their compiler to the frontend, then the following code should be useful for you.

(in-package :geb.lambda.main)

MAIN>
(to-circuit
 (lamb (list (coprod so1 so1))
              (index 0))
 :id)
(def id x1 = {
   (x1)
 };)

MAIN>
(to-circuit
 (lamb (list (coprod so1 so1))
              (case-on (index 0)
                              (lamb (list so1)
                                           (right so1 (unit)))
                              (lamb (list so1)
                                           (left so1 (unit)))))
 :not)
(def not x1 = {
   (((1 - x1) * 1) + (x1 * 0), ((1 - x1) * 1) + (x1 * 0))
 };)

MAIN> (to-circuit (lamb (list geb-bool:bool)
                        (left so1 (right so1 (index 0)))) :foo)
(def foo x1 = {
   (0, 1, x1)
 };)

For testing purposes, it may be useful to go to the BITC backend and run our interpreter

MAIN>
(gapply (to-bitc
         (lamb (list (coprod so1 so1))
               (case-on (index 0)
                        (lamb (list so1)
                              (right so1 (unit)))
                        (lamb (list so1)
                              (left so1 (unit))))))
        #*1)
#*00
MAIN>
(gapply (to-bitc
         (lamb (list (coprod so1 so1))
               (case-on (index 0)
                        (lamb (list so1)
                              (right so1 (unit)))
                        (lamb (list so1)
                              (left so1 (unit))))))
        #*0)
#*11

λ

13.1 Lambda Specification

[in package GEB.LAMBDA.SPEC]

This covers the various the abstract data type that is the simply typed lambda calculus within GEB. The class presents untyped STLC terms.

Accessors of ABSURD

Accessors of UNIT

Accessors of LEFT

Accessors of RIGHT

Accessors of CASE-ON

Accessors of PAIR

Accessors of FST

Accessors of SND

Accessors of LAMB

Accessors of APP

Accessors of INDEX

Accessor of ERR

Accessors of PLUS

Accessors of TIMES

Accessors of MINUS

Accessors of DIVIDE

Accessors of BIT-CHOICE

Accessors of LAMB-EQ

Accessors of LAMB-LT

Accessors of MODULO

λ

13.2 Main functionality

[in package GEB.LAMBDA.MAIN]

This covers the main API for the STLC module

λ

13.3 Transition Functions

[in package GEB.LAMBDA.TRANS]

These functions deal with transforming the data structure to other data types

One important note about the lambda conversions is that all transition functions except TO-CAT do not take a context.

Thus if the <STLC> term contains free variables, then call TO-CAT and give it the desired context before calling any other transition functions

λ

13.3.1 Utility Functionality

These are utility functions relating to translating lambda terms to other types

λ

14 Mixins

[in package GEB.MIXINS]

Various mixins of the project. Overall all these offer various services to the rest of the project

λ

14.1 Pointwise Mixins

Here we provide various mixins that deal with classes in a pointwise manner. Normally, objects can not be compared in a pointwise manner, instead instances are compared. This makes functional idioms like updating a slot in a pure manner (allocating a new object), or even checking if two objects are EQUAL-able adhoc. The pointwise API, however, derives the behavior and naturally allows such idioms

Further we may wish to hide any values inherited from our superclass due to this we can instead compare only the slots defined directly in our class

λ

14.2 Pointwise API

These are the general API functions on any class that have the POINTWISE-MIXIN service.

Functions like TO-POINTWISE-LIST allow generic list traversal APIs to be built off the key-value pair of the raw object form, while OBJ-EQUALP allows the checking of functional equality between objects. Overall the API is focused on allowing more generic operations on classes that make them as useful for generic data traversal as LIST(0 1)'s are

λ

14.3 Mixins Examples

Let's see some example uses of POINTWISE-MIXIN:

(obj-equalp (geb:terminal geb:so1)
            (geb:terminal geb:so1))
=> t

(to-pointwise-list (geb:coprod geb:so1 geb:so1))
=> ((:MCAR . s-1) (:MCADR . s-1))

λ

14.4 Metadata Mixin

Metadata is a form of meta information about a particular object. Having metadata about an object may be useful if the goal requires annotating some data with type information, identification information, or even various levels of compiler information. The possibilities are endless and are a standard technique.

For this task we offer the META-MIXIN which will allow metadata to be stored for any type that uses its service.

For working with the structure it is best to have operations to treat it like an ordinary hashtable

λ

14.4.1 Performance

The data stored is at the CLASS level. So having your type take the META-MIXIN does interfere with the cache.

Due to concerns about meta information being populated over time, the table which it is stored with is in a weak hashtable, so if the object that the metadata is about gets deallocated, so does the metadata table.

The full layout can be observed from this interaction

;; any class that uses the service
(defparameter *x* (make-instance 'meta-mixin))

(meta-insert *x* :a 3)

(defparameter *y* (make-instance 'meta-mixin))

(meta-insert *y* :b 3)

(defparameter *z* (make-instance 'meta-mixin))

;; where {} is a hashtable
{*x* {:a 3}
 *y* {:b 3}}

Since *z* does not interact with storage no overhead of storage is had. Further if `x goes out of scope, gc would reclaim the table leaving

{*y* {:b 3}}

for the hashtable.

Even the tables inside each object's map are weak, thus we can make storage inside metadata be separated into volatile and stable storage.

λ

15 Geb Utilities

[in package GEB.UTILS]

The Utilities package provides general utility functionality that is used throughout the GEB codebase

λ

15.1 Accessors

These functions are generic lenses of the GEB codebase. If a class is defined, where the names are not known, then these accessors are likely to be used. They may even augment existing classes.

λ

16 Testing

[in package GEB-TEST]

We use parachute as our testing framework.

Please read the manual for extra features and how to better lay out future tests