Objects, slots, methods, functions, and arguments
+ Associated example files
slippery chicken is written in and functions on the principles of the Common Lisp Object System (CLOS), the Common Lisp facility for object-oriented programming. While the user isn't required to understand the details of CLOS in order to be able to use slippery chicken, a brief introduction to a few core principles may help the beginning user to grasp some of the nomenclature and concepts found in the manual.
Like many other object-oriented languages, the basic building blocks in CLOS are classes and methods. The source code documentation for slippery chicken includes indexes for all of its classes and their associated methods.
+ Classes and slots
A class in slippery chicken, put very simply, is a generic blueprint for a type of container that holds a specific number of specific types of data. A class itself is essentially an empty copy of this type of container, with empty slots for the various items of data it is designed to store.
The user (or various internal routines in the software) can then create any number of objects using this blueprint. Each object made using this blueprint (each instance) will be a separate entity, but each will have the same structure, as defined in the blueprint for the class, and each will possess the same slots, which will contain specific data when the object is made. Once an object is created, the data in its slots can either be read or modified.
For example,
the named-object
class, which is the fundamental class in slippery chicken
from which all other classes are derived, has the
slots id
, tag
, and data
:
(defclass named-object () ((id :accessor id :initarg :id :initform nil) (tag :accessor tag :initarg :tag :initform nil) (data :accessor data :initarg :data :initform nil)))
Subclasses and inheritance
Classes can also be defined as subclasses of an already existing
class. Subclasses too, in turn, can be parent classes of further
subclasses. Any class that is a subclass of another class
also inherits the slots of its parent class in addition to
the slots that its own definition specifies. Thus, in addition to its
own warn-not-found
slot, the assoc-list
class, for example, also inherits all of the slots
of named-object
, linked-named-object
,
sclist
, and circular-sclist
, from which it
derives. Since all classes in slippery chicken derive from
the named-object
class, they all also have the
slots id
, tag
, and data
, even
though these are not specified in the class definition.
(defclass assoc-list (circular-sclist) ((warn-not-found :accessor warn-not-found :type boolean :initarg :warn-not-found :initform t)))
Making instances of class objects
Instances of class objects are created by using the CLOS
make-instance
function and passing values to the
object's slots using its slot accessor names as keyword arguments. In
addition, slippery chicken also has several built-in
functions (all starting with the word make-
) to
facilitate creating instances of various class objects. The latter is
the recommended means of creating objects and is described in more
detail below.
(make-instance 'assoc-list :id 'al-examp :data '((3 17) (ob bf3) (c4 q))) => ASSOC-LIST: warn-not-found T CIRCULAR-SCLIST: current 0 SCLIST: sclist-length: 3, bounds-alert: T, copy: T LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL NAMED-OBJECT: id: AL-EXAMP, tag: NIL, data: ( NAMED-OBJECT: id: 3, tag: NIL, data: 17 ************** NAMED-OBJECT: id: OB, tag: NIL, data: BF3 ************** NAMED-OBJECT: id: C4, tag: NIL, data: Q ************** ) **************
+ Methods
Methods in slippery chicken are the actions that can be
performed on the data contained in a class's slots. Some methods
generate the data to be placed into the slots. Other methods
manipulate data already stored there, and others just read and
retrieve the data already stored there. For example,
the get-first
method of
the assoc-list
class, which stores a list of items in its data
slot,
reads and retrieves the first item stored in that list:
(defmethod get-first ((al assoc-list)) (first (data al)))
An example of using a method. The class object must have already been created.
(let* ((al-object-1 (make-instance 'assoc-list :id 'al-object-1 :data '((3 17) (ob bf3) (c4 q))))) (get-first al-object-1)) => NAMED-OBJECT: id: 3, tag: NIL, data: 17
As with slots, methods too are inherited from parent classes.
+ Functions and arguments
Functions are routines that perform a predefined sequence of operations. Many of the functions in slippery chicken employ one or more methods. Functions can incorporate external values that are passed to them as arguments. These values can be the result of other routines, or may be specified by the user when the function is used. Some arguments are required, and some are optional.
Keyword arguments
One of the most frequent types of optional arguments used in slippery chicken is the keyword argument. None of the keyword arguments associated with a function must be called in order to use that function, but if one is used, the keyword itself must also be specified. In order to use a keyword argument in Common Lisp, it must be preceded by a colon.
The get-harmonics
function, for example, takes the required
argument fundamental
, and has the optional keyword
arguments start-at
, min-freq
,
and max-freq
, (which have default values
of 1
, 20
, and 20000
,
respectively):
(defun get-harmonics (fundamental &key (start-at 1) (min-freq 20) (max-freq 20000))
If the user wanted to employ this function and opt to specify values
for the start-at
and max-freq
arguments,
that would be done like so:
(get-harmonics 63 :start-at 2 :max-freq 1010) => (126 189 252 315 378 441 504 567 630 693 756 819 882 945 1008)
The source code documentation includes an index of all of the slippery chicken functions.
+ The make- functions
Nearly every class in slippery chicken has a function
associated with it that provides an easier way for the user (or the
software) to create objects of that class. These functions can be
recognized by the fact that their names start
with make-
.
Many of the make-
functions have keyword arguments that
can be used to set the values for the most important slots of the
class with which they are associated. In these cases, the given
keyword arguments are usually identical to the corresponding slot
names.
For example,
the rhythm
class has 23 different slots. The
associated make-rhythm
function has keyword arguments for two of them,
namely is-rest
and is-tied-to
. (The third
and fourth keyword arguments, duration
and tempo
, are not used to directly set the value of a
corresponding slot).
(defun make-rhythm (rthm &key (is-rest nil) (is-tied-to nil) (duration nil) (tempo 60.0))
The user can employ this function to make a rhythm
object, and can opt to specify values for these slots of that object
by setting the function's keyword arguments accordingly:
(make-rhythm 16 :is-rest t) => RHYTHM: value: 16.000, duration: 0.250, rq: 1/4, is-rest: T, score-rthm: 16.0, undotted-value: 16, num-flags: 2, num-dots: 0, is-tied-to: NIL, is-tied-from: NIL, compound-duration: 0.250, is-grace-note: NIL, needs-new-note: NIL, beam: NIL, bracket: NIL, rqq-note: NIL, rqq-info: NIL, marks: NIL, marks-in-part: NIL, letter-value: 16, tuplet-scaler: 1, grace-note-duration: 0.05 LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL NAMED-OBJECT: id: 16, tag: NIL, data: 16
+ make-slippery-chicken
The make-
function that the user will most frequently
employ
is make-slippery-chicken
. This
function is used to make an object of
the slippery-chicken
class (often referred to in this manual as a
"slippery-chicken
object").
The slippery-chicken
class currently has 29 slots, many
of which will contain objects of other classes when
the slippery-chicken
object itself is made, such as
an instrument-palette
object, an
ensemble
object, and a rthm-seq-palette
object, to name just a few. Many of the methods associated with the
slippery-chicken
class are used to make instances of
these sub-objects, or to set, read, and modify the data they
contain.
The make-slippery-chicken
function currently has 25
optional keyword arguments, most of which are used to directly set
the data contained in slots of the same name. Thus, when using the
make-slippery-chicken
function to create a composition,
the various blocks of code described in this User Guide will begin
with a colon, as they are the keyword arguments for the function. As
most of these keyword arguments are used to directly set the value of
a slot with the same name, it will often occur in this manual that
reference is made to the "instrument-palette
slot", for
example, rather than the ":instrument-palette
keyword".
Example of the simplest call
to make-slippery-chicken
:
(let* ((mini (make-slippery-chicken '+mini+ :ensemble '(((vn (violin :midi-channel 1)))) :set-palette '((1 ((c4 e4 g4)))) :set-map '((1 (1))) :rthm-seq-palette '((1 ((((2 4) q e e)) :pitch-seq-palette ((1 2 3))))) :rthm-seq-map '((1 ((vn (1)))))))) (midi-play mini) (cmn-display mini) (write-lp-data-for-all mini))
More information can be found about the specific classes, slots, methods, and associated functions in the source code documentation.