Newsgroups: comp.object,comp.lang.smalltalk,comp.lang.ada
Path: cantaloupe.srv.cs.cmu.edu!rochester!udel!news.mathworks.com!news.kei.com!bloom-beacon.mit.edu!world!bobduff
From: bobduff@world.std.com (Robert A Duff)
Subject: Re: Ada95 not OO (was Re: Has C++ had its day?)
Message-ID: <DBCq35.2tq@world.std.com>
Organization: The World Public Access UNIX, Brookline, MA
References: <NEWTNews.804269222.4596.sellers@sellers.sellers.com> <3th7u0$98g@Starbase.NeoSoft.COM> <DBBDGL.Kw5@world.std.com> <3tjeu7$la1@reuters2.mitre.org>
Date: Fri, 7 Jul 1995 15:09:05 GMT
Lines: 64
Xref: glinda.oz.cs.cmu.edu comp.object:34591 comp.lang.smalltalk:25587 comp.lang.ada:32246

In article <3tjeu7$la1@reuters2.mitre.org>, W. Wesley Groleau <wgroleau> wrote:
>If I'm wrong, please correct me without flames...

OK, you're wrong.  ;-)

>In an otherwise excellent posting, bobduff@world.std.com (Robert A Duff) made
>one incorrect aside:
>>Note that it is also possible to write a Union function that takes the
>>union of any two sets, no matter where they are in the hierarchy of set
>>types, including the case where one is a Bit_Vector and the other is a
>>Hash_Table_Set or whatever.  But that's not what I'm getting at here.
>
>Actually, a dispatching subprogram may not have more than one controlling
>parameter unless all of them have the same tag.

This is true, but doesn't contradict what I said.

You can use class-wide subprograms instead:

    function Classwide_Union(X, Y: Set'Class) return Set'Class is
        Result: Hash_Table_Set := Empty_Set;
    begin
        ... -- code to get each element of X, one by one, and insert
            -- it into Result.  Then do the same for Y.  Then:
        return Set'Class(Result);
    end Classwide_Union;

Classwide_Union is not a dispatching operation, so the same-tag rule
doesn't apply.

It will take a pair of sets (with any tags), and return a
Hash_Table_Set containing the union.  A more complicated
version might be smart enough to decide which kind of set
to create as the result based on how big it is, or something.
Or you could write different versions for each kind of set,
and let the caller decide what the result should be (but still
retain the capability of taking any kinds as arguments).
You could write more efficient versions for particular cases.
For example, you could put:

    if X'Tag = Y'Tag then
        return Union(X, Y); -- dispatch to the right one
    end if;
    ... -- code as above

in Classwide_Union, which would make it use the inefficient method only
when the tags are different.

In Smalltalk, you always get dispatching on the first argument (i.e. the
prefix -- the target of the message send), and you always get something
like the above class-wide behavior for the other arguments and the
result.

Again, I don't this is that big a deal -- you can still do OOP in
Smalltalk or C++ or Eiffel, even though they don't have this flexibility.
:-) :-)  (That was joke -- no flames, please!  Smalltalk at least has
the benefit of simplicity.)

Note that multi-methods, as in CLOS, are a much more powerful way of
dealing with this sort of example.  This, among other things, makes
CLOS more complicated that the OOP features of Ada, C++, and Smalltalk
put together!

- Bob
