clon
About
CLON stands for Common Lisp Object Network. It is different from CLOS in several important ways:
- CLON is prototype-based, not class-based. A prototype is a template object from which other objects are "cloned".
- Method invocation happens via message-passing, not generic functions; messages are conceptually different from synchronous function calls and may be freely queued, forwarded, and filtered.
- Built-in support for serialization.
-
Simple and small: as of December 2008,
clon.lispcontains about 750 lines of code and commentary. -
Special syntax support for message sending:
[method-name object arg1 arg2 ...]
and for accessing fields (i.e. "slots" in CLOS terminology):
(setf <field-name> value)
Download
Code example
First we must define a prototype and its fields:
(define-prototype rectangle () x y width height)
We could also have provided initialization forms and documentation strings:
(define-prototype rectangle ()
(x :initform 0
:documentation "The x-coordinate of the rectangle's top-left corner.")
(y :initform 0
:documentation "The y-coordinate of the rectangle's top-left corner.")
(width :documentation "The width of the rectangle.")
(height :documentation "The height of the rectangle."))
And if there was a "shape" prototype, from which we would like "rectangle" to inherit data and methods, we might have written:
(define-prototype rectangle (:parent =shape=)
(x :initform 0
:documentation "The x-coordinate of the rectangle's top-left corner.")
(y :initform 0
:documentation "The y-coordinate of the rectangle's top-left corner.")
(width :documentation "The width of the rectangle.")
(height :documentation "The height of the rectangle."))
Notice the equals signs surrounding the parent object's name; all objects made with define-prototype are accessible via special variables with such names.
The function CLON:CLONE is used to create new objects from these
prototypes. Now we write an initializer, which is passed any creation
arguments at the time of cloning:
(define-method initialize rectangle (&key width height) (setf <width> width) (setf <height> height))
Notice how field accesses can be written with the angle brackets; this
works both for reading and for writing, so long as you use setf for
the latter.
Now when you say:
(clone =rectangle= :width 5 :height 12)
The rectangle's initializer method is invoked with those arguments, and a rectangle of the correct height and width is created.
Now we define a few methods:
(define-method area rectangle ()
(* <width> <height>))
(define-method print rectangle (&optional (stream t))
(format stream "height: ~A width: ~A area: ~A"
<height> <width>
[area self]))
And invoke them with the aforementioned square bracket notation:
(defvar rect (clone =rectangle= :width 10 :height 8)) [print rect]
The result:
"height: 8 width: 10 area: 80"
Date: 2009-09-22 06:21:28 EDT
HTML generated by org-mode 6.30trans in emacs 23