For Development HEAD DRAFTSearch (procedure/syntax/module):

2.5 Integrated object system

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.

Everything is an object (if you care)

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:

Method is dispatched by all of its arguments.

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.

Class is also an instance.

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.

Class doesn’t create namespace

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.



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT