Lambda the Ultimate

inactiveTopic goo: a generic-function based OO language
started 4/17/2002; 1:20:33 AM - last post 4/22/2002; 4:22:13 PM
Michael Christopher Vanier - goo: a generic-function based OO language  blueArrow
4/17/2002; 1:20:33 AM (reads: 2195, responses: 12)
This link:

http://www.ai.mit.edu/~jrb/goo/index.htm

describes Goo, a "generic object-oriented" language that is roughly a cross between Dylan and Scheme. The language keeps scheme's minimalist syntax but is fully object-oriented all the way down, using a generic-function based multimethod dispatching object system similar to that found in Dylan or CLOS. The result is a language that appears to be exceptionally clean. Also comes with source code. This is definitely one to watch.

John Lawter - Re: goo: a generic-function based OO language  blueArrow
4/17/2002; 10:16:40 AM (reads: 2259, responses: 2)
The page states that "GOO supercedes proto" but I don't see any explanations of why Bachrach chose to start work on another language rather than refine proto. Did I miss something ?

Bryn Keller - Re: goo: a generic-function based OO language  blueArrow
4/17/2002; 3:02:05 PM (reads: 2332, responses: 1)
I think he did refine Proto, but he realized that prototypes weren't adequate for the type system he wanted to express, so he stopped calling it Proto. Here's what Eric Kidd had to say about it today:

I participated in these discussions, and I'll try to summarize some of the main points for you. Jonathan may want to correct me here. I only contributed a small amount of code to Goo, and none of my statements should be taken as anything more than personal opinions.

1. <foo> is typically not an instance of <foo>.

We found that--in most of our programs--that the prototype for class <foo> typically had several missing fields. These were filled in by individual instances cloned from <foo>. So (isa? <foo> <foo>) returned true, but the "class" <foo> did not obey the contracts of an "instance" of <foo>.

So a variable of type <foo> could hold either "subclasses" of <foo> or "instances" of <foo>. This had lots of weird consequences, and made some of our code smell funny.

Now, you could work around this by making sure that the "class" <foo> was also an "instance" of <foo>. This is quite easy for <rectangle> (just set all the co-ordinates to 0), but rather awkward for <input-stream> (what input should it return?).

2. We wanted first-class types.

Goo, like Dylan, makes extensive use of types. You can dispatch on them, instantiate them, introspect them, and use them in variable declarations.

Since types are a major, first-class abstraction in Goo, we wanted to have such classes as <type>, <class>, etc. But since you can't tell classes from instances in a prototype-based language, these abstractions never work right.

In short: "Dog" isn't a dog. The furry thing wandering down the hall is a dog. "Dog" is a word, or a platonic category, or a biological classification. But none of these things have long floppy ears and a tail.

Prototype-based languages are simple and easy to program. And if you have no more of a type model than SmallTalk, you probably don't even pay any conceptual penalty. But once you start having type declarations and first-class types, prototypes blur a useful distinction.

So it's basically a matter of taste, and consistency with other parts of the language design. (Language design is not an especially orthogonal problem--too many features interact in surprising ways.)

Cheers, Eric

Bryn Keller - Re: goo: a generic-function based OO language  blueArrow
4/17/2002; 3:41:14 PM (reads: 2403, responses: 0)
By the way, the name GOO seems to have originated here.

Chris Rathman - Re: goo: a generic-function based OO language  blueArrow
4/17/2002; 3:48:22 PM (reads: 2251, responses: 0)
Played around with a bit. Documentation could use some work. Had to kind of make guesses that varied between Scheme, CLOS and Dylan. The syntax is closer to Scheme, but the type system and method dispatch resembles Dylan. Obligatory Shape example for Goo to add to the list.

Chris Double - Re: goo: a generic-function based OO language  blueArrow
4/19/2002; 5:29:51 AM (reads: 2200, responses: 0)
Just some comments on the Shape example from a Goo beginner (but regular Dylan user).

In the properties for <shape> you define the properties x and y but also getters and setters. Why not just use the automatically provided getters and setters that come with the property (and which are just wrapper by your getter and setters)? This would get read of all the get-x, get-y, set-x, set-y stuff and let you use the 'set' generic.

This would make things like r-move-to easier to read and more 'goo-ish':

  
  (dm r-move-to (self|<shape> delta-x|<int> delta-y|<int>)
    (incf (x self) delta-x) 
    (incf (y self) delta-y))

Note that this is not like in C++ where you are wrapping 'public' variables. In Goo, properties already have function call syntax so replacing the property with a method later requires no change to client code.

The 'draw' method that is labeled 'mimic-abstract' could be just a generic function definition instead:

  (dg draw (self|<shape>))

This way you get an error if you call draw on a shape that doesn't add a method to the generic.

Thanks for posting the shapes example, hopefully more Goo examples will come out as the language matures.

Chris Rathman - Re: goo: a generic-function based OO language  blueArrow
4/19/2002; 9:20:23 AM (reads: 2166, responses: 0)
I agree with criticism of not using the idiom of the automatically generated getters/setters for the properties. But I'll probably leave it as is, since it maps better to the other example snippets.

I did change the code to take advantage of declaring an abstract class via the define generic (dg). I couldn't figure that one out on my own.

I do have a couple of questions related to lists and collections. I see in the documentation that the author is thinking about getting rid of lists in favor of collections (all but threatening to deprecate them in future revisions). I was wondering why the Goo authors would want to eliminate or restrict the use of lists?

In trying to build the example, I couldn't figure how the collections actually work, so I fell back to my Scheme experience and put them in a list:

   (def scribble (list
      (new <rectangle> x 10 y 20 width 5 height 6)
      (new <circle> x 15 y 25 radius 8)))

So how do you create a smalltalk equivalent of Bag in Goo to hold a collection of values, similar to the list above? I gather that the iteration loop (do loop) will work the same for lists and collections. But I couldn't figure out the manner to actually construct a Bag collection.

Chris Rathman - Re: goo: a generic-function based OO language  blueArrow
4/19/2002; 9:23:10 AM (reads: 2174, responses: 0)
Oh, and one other question. What's the difference between dm and df? Looks like one means define method and the other means define function. But I couldn't figure out any difference between the two.

Brent Fulgham - Re: goo: a generic-function based OO language  blueArrow
4/19/2002; 9:34:57 AM (reads: 2157, responses: 0)
I believe that "dm" means "Define Method" -- which generates what would be a regular function in the Scheme world.

"df" is "Define Generic Function", which uses Goo's multi-method dispatch using type information to select the closest method.

I'm not enough of a Goonosticator to say if this means that you do not get multi-method dispatch under "dm" or not... Perhaps someone smart can comment?

Brent Fulgham - Re: goo: a generic-function based OO language  blueArrow
4/19/2002; 10:06:29 AM (reads: 2169, responses: 0)
Jonathan was kind enough to correct my error:

not quite, df is define function (ala dylan), that is

(df f (...) ...) === (dv f (met (...) ...))

meaning that f is bound to a particular regular function from the scheme world, whereas, dm is define method (ala dylan), that is approximately

(dm f (...) ...)

=== (seq (unless (bound? f) (dv f (gen (...) ...))) (add-met f (met (...) ...)))

although the details aren't quite there (and this assumes special forms that aren't available to users), the basic idea is that dm defines and adds a method to a generic function on a given binding. dm ensures that an appropriate generic is defined on that binding before adding the method.

for example

(dm + (x|<int> y|<int> => <int>) ...)

adds a method to the + generic function stored in the + binding.

you should almost always use dm in your code (in preference to df) as this allows adding methods in the future.

reading the dylan reference manual will greatly clarify this.

Chris Double - Re: goo: a generic-function based OO language  blueArrow
4/19/2002; 4:18:41 PM (reads: 2111, responses: 0)
To create a vector of a particular size you can use:

  (dv x (fab <vec> 10))
  => $$<vec>(#f #f #f #f #f #f #f #f #f #f)

You can then set elements as required:

  (set (elt x 5) 55)

You can create a zero size collection and add to it as desired:

  (dv y (fab <vec> 0))
  (set y (add! y 20))

You can use 'packing' to do things like Common Lisps LOOP macro with COLLECT:

  (packing (pack 1) (pack 2))
    => (1 2)

Iteration and loops work the same over all collections:

  (for ((e  y)) (msg out "%s" e))  

Regarding df and dm - 'dm' is 'define method' and allows multi-method dispatch, OO and all that good stuff. 'df' is 'define function' and is basically a constant bound to a lambda expression. No method dispatch there. It's the equivalent in CLOS of:

;; dm
(defmethod foo ((a bar)) (format t "bar argument given"))
(defmethod foo ((a baz)) (format t "baz argument given"))

;; df (defun zap (a) (format t "no additional methods allowed"))

Chris.

Chris Rathman - Re: goo: a generic-function based OO language  blueArrow
4/22/2002; 8:48:07 AM (reads: 1891, responses: 0)
Ok, I think I understand the distinction between df & dm now. I also managed to figure out the collections based on the advice above. The code was redone as:
   ;; create a collection containing various shape instances
   (dv scribble (fab <vec> 1))
   (set (elt scribble 0) (new <rectangle> x 10 y 20 width 5 height 6))
(set (elt scribble 1) (new <circle> x 15 y 25 radius 8))

Only thing that threw me off is that the vector is zero-based and the number of elements is one greater than the number specified in the fab directive.

scruzia - Re: goo: a generic-function based OO language  blueArrow
4/22/2002; 4:22:13 PM (reads: 1870, responses: 0)
Brent says:
I'm not enough of a Goonosticator

The term has got to be "Goo-Roo". :-)