[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document:
The point of GOLD is that a non-trivial OO language can be defined in just a few dozen lines of LISP. For example, GOLD supports:
Amusingly, this help file is actually longer that the source code that implements GOLD.
GOLD is at least files:
inst
creation function such that
all objects get sent the init
message, immediately on creation.
init
to *object*
(so if your class does not have an init
method, then it still can be created
without a crash.
$prefix
.
zlots
.
with-zlots
.
Something is a subclass of *object*
with methods area,volume
and instance variables $height
.
(klass (*object*) area $height volume)
Note:
in GOLD, everything has to be a subclass of *object*
.
(defparameter *body* (klass (*object*) area $height volume))
As a side-effect of the above call, set and get methods are defined for
all the $variables
. So, after that call, it is possible to call:
($height abody) (setf ($height abody) 1)
Example:
(inst *body*)
Note: inst
is defined in terms of a lower-level inst0
function:
(defun inst (parent) (let ((obj (inst0 parent))) (init obj) obj))
So, if you want to turn off auto-initialization, then use the lower-level command inst0
.
Methods are just like LISP functions, with at least one argument (the instance being processed).
(defmeth volume *body* (me) (* ($height me) (area me)))
Note: if you get this error:
Can't set #<FUNCTION (LAMBDA (U)) {10043C9DA9}> of #1=#((#2=#((#3=#) #(INIT WITH-ZLOTS ZLOTS AREA ...
then have called defmeth
on a method name not listed in the call
to klass
that defined this class.
(defmeth init *body* (me) (setf ($height me) 1))
Note that such methods are optional. All sub-classes of *object*
inherit
a default, do nothing, initialization method.
Methods in sub-classes can access method definitions in super-classes via the next
function.
For example, suppose a *body*
has a default init
action which a sub-class called
*tube*
wants to access:
(defmeth init *body* (u) (setf ($height u) 1)) (defmeth init *tube* (u) (next u) (setf ($radius u) 10))
Bodies have a default height of one and a volume equal to their area times their height. Tubes are a sub-class of bodies whose area is their radius times pi, squared. Tubes initialize themselves as an extension to body’s initialization.
(defparameter *body* (klass (*object*) area $height volume)) (defparameter *tube* (klass (*body*) $radius)) (defmeth init *body* (u) (setf ($height u) 1)) (defmeth area *tube* (u) (* pi (expt ($radius u) 2))) (defmeth volume *body* (u) (* ($height u) (area u))) (defmeth init *tube* (u) (next u) (setf ($radius u) 10)) (defun !tube () (let ((tub (inst *tube*))) (format t "~a~%" (volume tub)) (with-zlots tub #'(lambda (prop value) (if (dollarp prop) (format t "~a = ~a~%" prop value))))))
Note the functions with-zlots
and dollarp
in the !tube
function.
The former loops through all slot names while the latter selects anything that starts
with a $
sign. This function just prints out all the instance variables (skipping
over the functions).
Functions that are generic to all objects can be written to *object*
methods.
For example:
(defmeth zlots *object* (self) (coerce (layout (parents self)) 'list)) (defmeth with-zlots *object* (self fn) (dolist (zlot (zlots self)) (funcall fn zlot (lookup zlot self))))
If *print-array*
is non-nil, then display a class will lead to an infinite loop
(since the first field contains a pointer back to itself, so a full print takes
never terminates).
GOLD
’s source code sets *print-array*
. However, in some obscure debugging
scenarios, this is not enough to stop the infinite loop. Therefore, if your code just hangs,
restart LISP
and make sure *print-array*
is nil.
See GOLD1 and 2; and GOLD3; and GOLD4.
[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on April 19, 2011 using texi2html 5.0.