OOP with GNU Guile and GOOPS
02 Mar 2014Having worked with the Ruby programming language for many years I started to get interested in Scheme. The Scheme programming language has a small and powerful core supporting closures, hygienic macros, first-class continuations, and of course the famous interpreter functions eval and apply.
However one thing I don’t like about Scheme is that there are different function names for each type of arguments. E.g. adding numbers is done with +, adding lists is done with append, and adding strings is done with string-append.
The same program would be much less verbose if + was extended to work with strings and lists, too:
GOOPS: The Guile extension for object-oriented programming
It turns out that GNU Guile (the Scheme interpreter of the GNU project) has a mature extension which facilitates this. GOOPS is inspired by the Common Lisp Object System (CLOS). GOOPS not only provides polymorphic methods, it even lets you replace existing functions with polymorphic ones:
The define-class method is the normal way to define a class. GOOPS requires you to define the instance attributes when defining the class. The following example defines a class <a> with attribute x and a + method. The make method is used to create the instance a of the class <a>.
Constructors and the next method
One can define a shorthand for instantiating objects. E.g. one can define a method which sets the attribute #:x to the argument multiplied by two.
IMHO it is better though to define a modified constructor directly. This is more involved but also possible.
Note the call to next-method. This essentially calls the next less specialized method for that generic function. Here is another example using an inheriting class <b> to illustrate the concept.
Metaclasses
Note that GOOPS does not implicitly create a metaclass. The following example shows how to define a metaclass <m<c>> with a class method.
Inspection
One can also use GOOPS to change the way how objects get displayed and what the REPL writes to the terminal. E.g. one can define the method write for the class <a> to change the way the Guile REPL displays objects of that class.
Furthermore one can implement the method display to define the way objects get displayed in formatted output.
Conclusion
I have now used GOOPS for a little while. Coming from Ruby there are a few gotchas when using GOOPS and Guile’s module system. For example one needs to use a #:re-export statement when using a module to replace the core binding for the + operator.
All in all GOOPS makes quite a mature impression and I think it makes Scheme much more amenable to developers who are used to thinking in terms of objects and classes.
To quote Guile’s foreign function interface documentation:
The more one hacks in Scheme, the more one realizes that there are actually two computational worlds: one which is warm and alive, that land of parentheses, and one cold and dead, the land of C and its ilk.
Any comments and suggestions are welcome
Further remarks
If necessary it is also possible to create objects, classes, and metaclasses dynamically. The following example instantiates the object v of class <v> of metaclass <m<v>>. Furthermore the generic test is implemented for <v>.
Update:
I tweeted about the article and submitted it to Hackernews and the GUILE user list.
I have reduced the use of slot-ref during a discussion on the GUILE user list.
See also: