This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Some questions about GOOPS and CLOS in general


Jost Boekemeier <jostobfe@calvados.zrz.TU-Berlin.DE> writes:

> <product>.multiply(<factor>, <factor>);
> 
> The method `*' clearly belongs to the class <product>.  One can say that
> the class <product> modifys itself.  In any case, its methods can't
> modify instances of other classes!

C++: A * B
TOM: [A multiply B]
CLOS: (multiply A B)

So... huh?!

> When you write (* <matrix> <vector>) this is either a functional
> style (i.e. the function returns a value) or it is OO style
> (i.e. the method manipulates a data structure).

In any OO paradigm I've worked with, methods return values without
problems.

> In the OO paradigm you don't associate methods with classes.  They
> *belong* to exactly one class' object and they will go away when the
> object goes away.

In some particular OO paradigms. Obviously, not in CLOS and not in
GOOPS. So this argument is obviously not general enough to be of any
value to this discussion.

> Protection.  How can one prevent a method from accidently modifying
> several objects. How can one hide slots from beeing touched by foreign
> methods?  Removing the slot-ref/set! functionality and letting the
> surounding module handle protection (the module exports the getter/set
> methods) seems to be a good choice.
> 
> The problem is that this introduces redundancy.  The class "knows"
> which other classes it needs.  But the module doesn't know that.
> Therefore you have to type the same information twice: Class c extends
> class a and therefore you must tell the current module C to import the
> class a from module A.

The problem is that this introduces redundancy. The function "knows"
which other functions it calls. But the module doesn't know
that. Therefore you have to type the same information twice: function
f calls function g, and therefore you have to tell the current module
F to import a function from module G.

Um. No further questions, y'honor.

On another line, one of the basic assumptions of CLOS is that
encapsulation is orthogonal to OO - in other words, Java
implementation of modules as singletons is Java's design choice rather
than obvious thing to do in any OO system.

For example, it's a really good idea to program all the matrix classes
in one module - direct access to slots, assuming you can compile the
code - allows you to omit *lots* of annoying method calls, while still
keeping clean exported interface (this is in a way similar to GC,
where low-level stack manipulation is hidden between 'you never type
delete' interface).

> Yes.  His paper is about a type system with inheritance.  Normally a
> type system is ortogonal to a module system: The type system handles
> the logical structure of the software and the module system handles
> the physical structure.

Precisely - so why do you insist on encapsulating classes?

> But he treats modules just like classes and I quite like the trick.
> Normaly a module /owns/ one or more classes.  In his system a module
> /is a/ class.

Class in GOOPS is a type.

> Not quite.  I am searching for a way to smoothly integrate an object
> system into the module system.  This is part of my "porting goops to
> the new environment-system" effort. :)  Although GOOPS is the only 
> OO system we have at the moment I want to keep the interface as 
> open as possible.

My suggestion would be not to try to integrate it at all - the two are
separate entities by design, as one handles datatypes and the other
encapsulation.

> > (m1 a) -> 2                             (fc1 color) -> 1
> > 
> > In a way, I think this syntax is disturbing.  In Scheme, I'm used that
> > the first element in an expression is an operator.  But here, fc1 is
> > in fact an object.
> 
> Yes.  But as Craig already said: "Natural is a POV issue." :)

Natural in Scheme is same as in Gaelic - the verb comes first.

So (fc1 method arg...) is VERY misleading to anybody who tries to read
this code, if you emphasize that fc1 contains data.

Even if fc1 is a lambda, this is misleading. It is also vastly
inferior to any OO with multiple dispatch (see below).

> But you can't hide the fact that the OO paradigm turns the generic
> style used in scheme upside down (the explicit type system is
> another example).

OO paradigm you seem to be advocating to the exclusion of all others
seems to do, yes.

> a can either be a method, a "getter" or "setter" or a slot.  m1 can
> and will handle all these cases correctly.  But it is true that you
> must quote the selector `a' which is simply a symbol.

To repeat: while this is true, this method can't give you polymorphism
of the sort (m1 format binary-formatter) vs (m1 format text-formatter)
- m1 would have to dispatch explicitely at some point. In a strongly
typed language, the two would be distinct methods at compile time
(provided that formatter is not a pointer, otherwise, the two would be
segfault waiting to happen). In Scheme, MD is a must. And with MD
comes the fact that it isn't at all clear which class dispatches on
format (the correct answer is 'both').

> > There is the risk of getting confused when the only difference between
> > assignment and reference is the number of elements in the application.
> 
> A method with no arguments returns the slot (is a getter) or a setter
> with an implicit argument, for example (fc1 'set-color-to-1).  A method
> with 3 or more arguments is a always setter.

How about (get-nth list 5) ?

This has to be accessor of some sort, in order for

(generic-set! (get-nth list 5) 15)

to work.

-- 
How to eff the ineffable?

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]