Gauche has a STklos-style object system, similar to CLOS. If you have used some kind of object oriented (OO) languages, you’ll find it easy to understand the basic usage:
;; Defines a class point, that has x and y coordinate
(define-class point ()
((x :init-value 0)
(y :init-value 0))
)
(define-method move ((p point) dx dy)
(inc! (slot-ref p 'x) dx)
(inc! (slot-ref p 'y) dy))
(define-method write-object ((p point) port)
(format port "[point ~a ~a]"
(slot-ref p 'x)
(slot-ref p 'y)))
However, if you are familiar with mainstream OO languages but new to CLOS-style object system, Gauche’s object system may look strange when you look deeper into it. Here I describe several characteristics of Gauche object system quickly. See Object system, for details.
You have seen this tagline for the other languages. And yes, in Gauche, everything is an object in the sense that you can query its class, and get various meta information of the object at run time. You can also define a new method on any class, including built-in ones.
Note that, however, in CLOS-like paradigm it doesn’t really matter whether everything is an object or not, because of the following characteristics:
Unlike other object-oriented languages such as C++, Objective-C, Python, Ruby, etc., in which a method always belong to a single class, a Gauche method doesn’t belong to a specific class.
For example, suppose you define a numeric vector class
<num-vector>
and a numeric matrix class <num-matrix>
.
You can define a method product
with all possible combinations
of those type of arguments:
(product <num-vector> <num-matrix>) (product <num-matrix> <num-vector>) (product <num-vector> <num-vector>) (product <num-matrix> <num-matrix>) (product <number> <num-vector>) (product <number> <num-matrix>) (product <number> <number>)
Each method belongs to neither <num-vector>
class nor
<num-matrix>
class.
Since a method is not owned by a class, you can always define your
own method on the existing class (except a few cases
that the system prohibits altering pre-defined methods). The above
example already shows it; you can make product
method work
on the built-in class <number>
. That is why I said
it doesn’t make much sense to discuss whether everything is object
or not in CLOS-style object system.
To step into the details a bit, the methods are belong to a generic function, which is responsible for dispatching appropriate methods.
By default, a class is also an instance of class
<class>
, and a generic function is an instance of class
<generic>
. You can subclass <class>
to customize
how a class is initialized or how its slots are accessed.
You can subclass <generic>
to customize how the
applicable methods are selected, which order those methods are
called, etc. The mechanism is called metaobject protocol.
Metaobject protocol allows you to extend the language by
the language itself.
To find examples, see the files lib/gauche/singleton.scm
and
lib/gauche/mop/validator.scm
included in the distribution.
You can also read lib/gauche/mop/object.scm
, which actually
defines how a class is defined in Gauche.
For more details about metaobject protocol, see
Gregor Kiczales, Jim Des Rivieres, Daniel Bobrow,
The Art of Metaobject Protocol,
The MIT Press.
In the mainstream OO language, a class often creates its own namespace. This isn’t the case in CLOS-style object system. In Gauche, a namespace is managed by the module system which is orthogonal to the object system.