Replacing Multiple Inheritance with Java's Interfaces 
Author Message
 Replacing Multiple Inheritance with Java's Interfaces

Quote:
> OK, from the discussion here I'm convinced that multiple dispatch is worth
> another look.  (Apparently the first look was less than thorough ...)

> My next question is, where can I find an inexpensive (or free?)
> implementation of a multiple-dispatch language -- nothing high-performance
> necessarily, just something to explore with.

There are a number of free Common Lisps -- see the FAQ postings in
Comp.lang.lisp.  (The object system in Common Lisp (CLOS) has multi-arg
dispatch.

(In some cases, for historical reasons, the CLOS may not be build-in
and you may have to add an implementation such as PCL.  I think GCL
(GNU Common Lisp) is still in this class.)

There are also some object systems other than CLOS that can be used
Common Lisp, and another set that can be used with Scheme.  Many of
then provide multi-arg dispatch.  Consult the FAQ postings for Comp.
lang.lisp and Comp.lang.scheme.

It's also pretty easy (a couple of pages) to write simple object
systems that handle multi-arg dispatch for Scheme or Common Lisp.

-- jeff



Sat, 25 Sep 1999 03:00:00 GMT  
 Replacing Multiple Inheritance with Java's Interfaces

Re: a free object system with multiple dispatch

Gambit-C is a free, high-performance scheme implementation; it can be
found at

http://www.iro.umontreal.ca/~gambit

Meroon is a CLOS-like object system for Scheme that has been
integrated rather well with Gambit, in that Marc Feeley, the author
of Gambit, has made Meroon objects an integrated type in Gambit, like
structures.  Meroon has multiple dispatch, but not multiple inheritance.
Meroon can be found at:

   ftp://ftp.inria.fr/INRIA/Projects/icsla/Programs/Meroon-V3*.tar.gz

Instructions for loading and compiling Meroon for Gambit 2.5.1 are below.


If one likes, one can concatenate all the meroon source files (in the right
order) to make one large file; the version for MeroonV3-97Feb12 can be
found at

ftp://ftp.math.purdue.edu/pub/lucier/_meroon.scm

This includes the following declarations for speed at the front of the file:

(declare (block) (standard-bindings) (extended-bindings) (fixnum) (not safe))
(declare (not interrupts-enabled))

To load meroon:

Define:

(define (old-load filename)
  (call-with-input-file
    filename
    (lambda (port)
      (##read-expressions-from-port
        port
        (lambda (script? exprs)
          (for-each eval exprs))))))

then

(old-load "_meroon.scm")

To compile meroon:

(old-load "_meroon.scm")

(compile-file "_meroon.scm")

and one loads the compiled version with

(load "_meroon")

If you don't have the swap space to do this, then one can try several things.
First, one can disable inlining, by adding to the top of the file.

(declare (not inline) (inlining-limit 0))

Next, one might try setting the optimization level to -O0 in gcc (or your
own C compiler).  Finally, one could define ___MULTIPLE_HOSTS rather
than ___SINGLE_HOST for the C compile.



Sat, 25 Sep 1999 03:00:00 GMT  
 Replacing Multiple Inheritance with Java's Interfaces

Quote:

> My next question is, where can I find an inexpensive (or free?)
> implementation of a multiple-dispatch language -- nothing high-performance
> necessarily, just something to explore with.

CMU's CLOS seems like a good choice (it's free...)

/Jon
--
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383



Sat, 25 Sep 1999 03:00:00 GMT  
 Replacing Multiple Inheritance with Java's Interfaces

:You're right, the ways to manage this in traditional OO -- principally the
:Visitor pattern from the Gang of Four -- make this sort of thing tricky.  
:Many times, though, you can find some simplifying condition: ..

In the case of Eiffel, another specific case allows an elegant solution.
In the special case where, for each value of a parameter, there is only one
corresponding value for each of the other parameters, you can use covariance.

If a something more general is required, you need to use one of the techniques
for emulating multiple dispatching.

Don.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-



Sun, 26 Sep 1999 03:00:00 GMT  
 Replacing Multiple Inheritance with Java's Interfaces

:
::You're right, the ways to manage this in traditional OO -- principally the
::Visitor pattern from the Gang of Four -- make this sort of thing tricky.  
::Many times, though, you can find some simplifying condition: ..
:
:In the case of Eiffel, another specific case allows an elegant solution.
:In the special case where, for each value of a parameter, there is only one
:corresponding value for each of the other parameters, you can use covariance.

Oops! That's not quite right. I should have said:

In the special case where, for each value of a parameter,

  a) The corresponding value for each of the other parameters is a particular
     value (or a more specific one), and
  b) The values of parameters become more specific in tandem,

you can use covariance.

Don.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-



Sun, 26 Sep 1999 03:00:00 GMT  
 Replacing Multiple Inheritance with Java's Interfaces



Quote:
>However, I will assert that there is indeed a penalty for multi-arg dispatch.
>Namely that the unit of access control (encapsulation) is no longer the
>same as that of class or type.

>Some people believe this to be a benefit: 'it is more orthogonal'.

I don't know if I would consider it a "benefit", but rather that it's not
that much of a loss.  Some of us consider strong enforcement of
encapsulation to be highly overrated.  It should not be up to the
programming language to force you to use good programming practices.
Proper adherence to conventions will get you most of the benefits of
encapsulation.  And violations of many of these practices can be detected
using lint-style tools.  Namespace-management techniques (CL packages, C++
namespaces) are also useful in this regard, although they're generally
designed for large granularity.

For instance, access to instance variables (AKA slots or member variables)
should always be via generic function calls; the only exceptions to this
would be the definitions of the accessor methods themselves (which might be
defined automatically, as in CLOS).
--
Barry Margolin
BBN Corporation, Cambridge, MA

(BBN customers, call (800) 632-7638 option 1 for support)



Mon, 04 Oct 1999 03:00:00 GMT  
 Replacing Multiple Inheritance with Java's Interfaces

:>
:> Consider a set of 2d geometric classes: regions (with subclasses
:> point, line, ellipse, polygon) and transforms (with subclasses
:> identity, translation, and general).  Implement the function
:> 'transform-region' which, given a transform and a region, applies
:> the transform to the region and returns a new region.  I think you
:> will find that multiple dispatch is a major win here.
:
:Or a set of geometric classes with operations union and intersection.
:With multiple dispatch, you can have intersection methods specialized
:on both arguments ( intersect(line, rectangle), intersect(rectangle,
:rectangle), etc.)

In general, any time you have a true 'n1 x n2' dispatch, where n1 and
n2 are the cardinalities of the set of concrete classes for argument types
'1' and '2'.

However, I will assert that there is indeed a penalty for multi-arg dispatch.
Namely that the unit of access control (encapsulation) is no longer the
same as that of class or type.

Some people believe this to be a benefit: 'it is more orthogonal'.  Indeed
it is so, but I feel that in empirical practice the set of
requirements *usually* tends to lie heavily along one principal axis:

  that 'non-orthogonal' axis where the unit of
     1) allocation
     2) encapsulation
     3) inheritance
     4) type
     5) mutable state
  are combined in one useful concept, otherwise known as an Eiffel-style
  'class'.

The situations mentioned above are the exceptions of course.  The penalty
for separating access control from type is a substantial increase in the
textual and intellectual "bureaucracy" needed to write idiomatic
object-oriented programs.  See, for instance, Ada95.

Along these lines, concepts like David Shang's more interesting forms of
genericity also seem to cover a number of useful situations in a more
specifically idiomatic way than a raw n1 x n2 multidispatch.

:Jonathan Moody

--
Matthew B. Kennel/Institute for Nonlinear Science, UCSD/
Don't blame me, I voted for Emperor Mollari.



Mon, 04 Oct 1999 03:00:00 GMT  
 Replacing Multiple Inheritance with Java's Interfaces


Quote:
> However, I will assert that there is indeed a penalty for multi-arg dispatch.
> Namely that the unit of access control (encapsulation) is no longer the
> same as that of class or type.

Many people believe this to be the correct approach, and consider the
Eiffel/Sather confusion of module and type to be flawed.

Quote:
> Some people believe this to be a benefit: 'it is more orthogonal'.  Indeed
> it is so, but I feel that in empirical practice the set of
> requirements *usually* tends to lie heavily along one principal axis:

How do we parse "in empirical practice"? Do you mean that you've analyzed
large bodies of code in many languages, and drawn these conclusions? I am
skeptical.

Quote:
>   that 'non-orthogonal' axis where the unit of
>      1) allocation
>      2) encapsulation
>      3) inheritance
>      4) type
>      5) mutable state
>   are combined in one useful concept, otherwise known as an Eiffel-style
>   'class'.
> The situations mentioned above are the exceptions of course.  The penalty
> for separating access control from type is a substantial increase in the
> textual and intellectual "bureaucracy" needed to write idiomatic
> object-oriented programs.  See, for instance, Ada95.

Please elaborate (pun intended). What is an idiomatic OO program? I think
"idiomatic" would have to refer to a particular language or
implementation.

Also, I am very familiar with Ada 95, and while there are certain problems
of Ada which I imagine you have in mind (i.e., mutually recursive types
which are in different packages?), there are many proposed enhancements
to the language which rectify these without changing the basic structure
of Ada, so your argument seems weak. Lets see real examples of
"idiomatic OO programs", and your attempts at an Ada translation,
and then we'll see if it is actually the module/type separation that is
causing the problem. Also, perhaps you should crosspost to the Ada newsgroup
instead of the Dylan one if you wish to analyze perceived flaws in that
language.

In the case of Dylan, I might turn your argument back to you and suggest
that the Eiffel "everything a class" view leads to an increase in the
textual and intellectual bureaucracy needed to write idiomatic functional
programs, as simulating closures with classes is clumsy. I know that
Eiffelists will disagree, and I've seen the arguments and am unconvinced.
It appears that the designers of Sather were too, since they added closures
and iterators to their Eiffelesque base.

Quote:
> Along these lines, concepts like David Shang's more interesting forms of
> genericity also seem to cover a number of useful situations in a more
> specifically idiomatic way than a raw n1 x n2 multidispatch.

I guess I'll reserve judgement until working implementations are out. Lots
of things sound good "on paper" (system level validity checking in Eiffel?)
but never seem to make it on silicon.

-- Brian



Tue, 05 Oct 1999 03:00:00 GMT  
 Replacing Multiple Inheritance with Java's Interfaces




:>However, I will assert that there is indeed a penalty for multi-arg dispatch.
:>Namely that the unit of access control (encapsulation) is no longer the
:>same as that of class or type.
:>
:>Some people believe this to be a benefit: 'it is more orthogonal'.
:
:I don't know if I would consider it a "benefit", but rather that it's not
:that much of a loss.  Some of us consider strong enforcement of
:encapsulation to be highly overrated.  

:It should not be up to the
:programming language to force you to use good programming practices.

This is a major philosophical contention.  I firmly disagree.

I see the history of programming language as turning fuzzy
ideas, notions, good practices and 'techniques', into solid,
standardized technology.  This is otherwise known as 'progress'.

For example, does the provision of a "subroutine" (a major advance
of fortran I) encourage or force somebody to use
"good programming practice"?

Most people today would reflexively answer 'no', but I suspect this
is because such a concept is so deeply tucked in the basic outlook of
programmers today.

From the point of view of a programmer in 1947, it certainly does look
like language designers trying to impose an opinion about
"good programming practice".

At some level, every design choice of a programming language
represents somebody's opinion of "how things ought to be".

I know this is controversial, but I feel saying "It is not up to
the programming language to force you to use good programming
practices" doesn't say that much more than "I don't like
it when it does X Y and Z" for certain values of X, Y and Z.

:--
:Barry Margolin
:BBN Corporation, Cambridge, MA

:(BBN customers, call (800) 632-7638 option 1 for support)

--
Matthew B. Kennel/Institute for Nonlinear Science, UCSD/
Don't blame me, I voted for Emperor Mollari.



Fri, 08 Oct 1999 03:00:00 GMT  
 Replacing Multiple Inheritance with Java's Interfaces

:

:> However, I will assert that there is indeed a penalty for multi-arg dispatch.
:> Namely that the unit of access control (encapsulation) is no longer the
:> same as that of class or type.
:
:Many people believe this to be the correct approach, and consider the
:Eiffel/Sather confusion of module and type to be flawed.

Of course, otherwise they wouldn't have done otherwise.

:> Some people believe this to be a benefit: 'it is more orthogonal'.  Indeed
:> it is so, but I feel that in empirical practice the set of
:> requirements *usually* tends to lie heavily along one principal axis:
:
:How do we parse "in empirical practice"? Do you mean that you've analyzed
:large bodies of code in many languages, and drawn these conclusions? I am
:skeptical.

No of course not. It's my personal experience.  However, there is
little true experimental evidence about most aspects of programming
language design.

:>   that 'non-orthogonal' axis where the unit of
:>      1) allocation
:>      2) encapsulation
:>      3) inheritance
:>      4) type
:>      5) mutable state
:>   are combined in one useful concept, otherwise known as an Eiffel-style
:>   'class'.
:
:> The situations mentioned above are the exceptions of course.  The penalty
:> for separating access control from type is a substantial increase in the
:> textual and intellectual "bureaucracy" needed to write idiomatic
:> object-oriented programs.  See, for instance, Ada95.
:
:Please elaborate (pun intended). What is an idiomatic OO program? I think
:"idiomatic" would have to refer to a particular language or
:implementation.

:Also, I am very familiar with Ada 95, and while there are certain problems
:of Ada which I imagine you have in mind (i.e., mutually recursive types
:which are in different packages?), there are many proposed enhancements
:to the language which rectify these without changing the basic structure
:of Ada, so your argument seems weak. Lets see real examples of
:"idiomatic OO programs", and your attempts at an Ada translation,
:and then we'll see if it is actually the module/type separation that is
:causing the problem.

I don't know Ada well enough to write programs in it.  I base my opinion
on trying to make small Sather programs which reproduce the functionality
of various Ada fragments which were posted on Usenet with enough
annotation that I could figure out.   (This came about a year or two ago).

For example: reproduce a program like

-- Begin trivial Sather example.
class A is
  attr a:A;
  attr b:B;
end

class B is
  attr a:A;
  attr b:B;
end

in Ada.  (Remember that a and b are reference variables).  I also
remember many people saying how it would be "good OO practice" to
have one type per package.

Remember, I'm not putting forth an argument of "can or cannot do", but
"would rather or would rather not".

:Also, perhaps you should crosspost to the Ada newsgroup
:instead of the Dylan one if you wish to analyze perceived flaws in that
:language.

I'm sorry, but they know my opinion already.  I'll take off comp.lang.dylan
and stick to comp.object only for followups, as this issue is
somewhat broad.

:In the case of Dylan, I might turn your argument back to you and suggest
:that the Eiffel "everything a class" view leads to an increase in the
:textual and intellectual bureaucracy needed to write idiomatic functional
:programs, as simulating closures with classes is clumsy. I know that
:Eiffelists will disagree, and I've seen the arguments and am unconvinced.
:It appears that the designers of Sather were too, since they added closures
:and iterators to their Eiffelesque base.

Yes.  I like the improvements in iterators and closures that Sather
brings to Eiffel.   However, there was no percieved need to change the
Eiffel unification of type and class, which I thought was the issue
in contention.

Doing things the Eiffel way also brings up the opportunity to clearly support
a "design by contract" outlook.   I think this is important, as it
offers specific guidance about the way to write good programs.  A substantial
amount of object oriented design books use these ideas, whether explicitly
or implicitly, to discuss the writing of programs.

Now, if one separates type from class, what is the "unit of the contract"?
Who is reponsible for what?

I don't feel that equally good notions about how to write programs
when separating type from encapsulation have been made and popularized.

Ada95 is the way it is on account of some historical compatibility
with Ada83 packages.  Dylan, the same, on account of Lisp tradition.

:> Along these lines, concepts like David Shang's more interesting forms of
:> genericity also seem to cover a number of useful situations in a more
:> specifically idiomatic way than a raw n1 x n2 multidispatch.
:
:I guess I'll reserve judgement until working implementations are out. Lots
:of things sound good "on paper" (system level validity checking in Eiffel?)
:but never seem to make it on silicon.

Of course.  OTOH, I feel that {*filter*}ly separating type from class as
more 'orthogonal' is also an idea which sounds better "on paper" than
in real life.

Certainly there are better ideas still that have yet to be
discovered.

:-- Brian

--
Matthew B. Kennel/Institute for Nonlinear Science, UCSD/
Don't blame me, I voted for Emperor Mollari.



Fri, 08 Oct 1999 03:00:00 GMT  
 Replacing Multiple Inheritance with Java's Interfaces

Quote:

> Now, if one separates type from class, what [...]

"Separates type from class" sounds like an abbreviation, but I am not sure
what for. Here's an example. Suppose I have String and Stream classes, and
write a routine (in a made-up language):

     void output( String string, Stream stream ) {
         for (int i = 0; i < length( string ); i++)
              output( characterAt( string, i ), stream );
     }

The intent is that this be dynamically dispatched on both arguments, so
that I can output other kinds of object to other kinds of media.

My point is that I can write this using only the public interfaces of
String (length and characterAt) and Stream (output). So multimethods do
not _need_ to break encapsulation. I would very much like to see a
language which made "dynamic dispatching" orthogonal to "class
membership". In this language, characterAt( String, Int ) would be a
member of the String class, and output( String, Stream ) would not be a
member of any class.

I strongly believe in abstract data types; I believe the core of the OO
class concept is the notion of a fixed, finite list of routines which may
directly access the representation of an entity. And I believe in static
type checking, and the Eiffel-like unification of class and type that you
seem to advocate. But I see this as orthogonal to dispatching. Why must
the ability to dispatch on a given argument be tied to the right to access
that argument's private representation?

So I think "separating type from class" is not the key approach to
multiarg dispatch.

Quote:
> Now, if one separates type from class, what is the "unit of the
> contract"?
> Who is reponsible for what?

Routines would still have pre- and post-conditions. The invoking code
would be responsible for ensuring the pre-condition of at least one
implementation of output. I don't see any big problem here.

There is a potential problem in checking that every call of output can be
satisfied. One would like to do this check statically. With careful
language design, this may be possible. Cecil and Dylan have made some
progress.

However, the few languages I know which support multimethods, dispatch on
implementation rather than on interface. I think this is wrong. I'd like
to hear of any language which does things the way I describe above.

   Dave Harris, Swansea, UK   | "Weave a circle round him thrice,

                              |  For he on honey dew hath fed
 - I speak only for myself -  |   And drunk the milk of Paradise."



Fri, 08 Oct 1999 03:00:00 GMT  
 multiarg dispatch.


Quote:
>:It should not be up to the
>:programming language to force you to use good programming practices.

>This is a major philosophical contention.  I firmly disagree.

For the record, so did the people designing Dylan.  Throughout the
design process, we tried to adopt language features that encouraged
a programming style that would lead to clear, maintainable code.

On the subject at hand, we felt that the conflation of classes with
namespaces was just that: a conflation that made code artificially
awkward, led to unnecessary convolutions to work around arbitrary
restrictions, and that therefore it encouraged poor programming
practices.

  -Andrew

--

You never ever get bored because you're always sore.
                                          -Susie Maroney
                                           long-distance swimmer



Fri, 08 Oct 1999 03:00:00 GMT  
 multiarg dispatch.


Quote:
> <snip>
> For example, does the provision of a "subroutine" (a major advance
> of Fortran I) encourage or force somebody to use
> "good programming practice"?
> <snip>

Minor quibble. Fortran (I) introduced the procedure in the form of the
FUNCTION. Fortran II introduced the SUBROUTINE. (Although the initial
proposal for Fortran included the concept of the subroutine, the
implementation wasn't ready when they decided in the third year of a one
year project that they had to get something out the door.)

--

William B. Clodius              Phone: (505)-665-9370
Los Alamos Nat. Lab., NIS-2     FAX: (505)-667-3815
PO Box 1663, MS-C323            Group office: (505)-667-5776



Sat, 09 Oct 1999 03:00:00 GMT  
 
 [ 30 post ]  Go to page: [1] [2] [3]

 Relevant Pages 
 

 
Powered by phpBB® Forum Software