Here are some problems/limitations of existing OO/GF systems that I
don't intend to repeat:

A) They provide only a single declaration point for all superclasses
of a class
B) They consider the local declaration order of superclasses to be
significant
C) They conflate hierarchies and graphs containing sideways edges
having nothing to do with hierarchy
D) They provide only a single slot for type/class per object
E) They allow conflicting local superclass declaration orders,
creating cycles in the graph not detected until subsequent derivation

Image:

(class Horse :supers [Animal])

Now suppose some user of Horses, but not the library author, wants to
consider Horses to be Transportation. Due to (A) they can't, without
convincing the author of the library to change the declaration to
include Transportation in the supers:

(class Horse :supers [Animal Transportation])

Here's where (B) rears its ugly head. At this point in time there may
be no significant basis for determining the order in which these
declarations should occur. It is not an inherent property of the
derivation relationship (C), but must be specified here and now due to
the fact that the derivation declaration does 2 jobs (derivation +
precedence). It might never matter, but if it does matter it will be
because eventually some method is defined on both Animal and
Transportation, and a decision needs to be made as to which should
apply to Horse, e.g.:

(allowed-on-road Animal) -> false
(allowed-on-road Transportation) -> true

in order to make (allowed-on-road Horse) work the way we want (i.e.
true), and presuming we want to inherit our behavior rather than
specify it (the laziness presumption), we'd prefer Transportation
precede Animal in the supers declaration of Horse. Another trip to the
library author.

Here's where (D) rears its ugly head - this is a global declaration
that universally applies. One could easily imagine another method
where it would be preferable that Animal preceded Transportation when
applied to Horses (the library author might say no)

As for (E), if we later create:

(class Camel :supers [Transportation Animal])

no advances in genetics can allow us to make a HorseCamel, since the
resulting graph can't be ordered. (We can't put HC on the front of a
merge of H->A->T and C->T->A that preserves their relative orders)

These are just OO devices, not logical systems - they are just
arbitrary mechanisms full of corner cases and creeping complexity. I
don't know why we are in such a hurry to recreate them.

----------------------------
Here's how I think about it:

- Hierarchies have nothing to do with multimethods/GFs per se.
- They are created by independent, atomic, logical statements about
derivation relationships
- Those statements can come in any order, or place
- The logical statements are validated to not create cycles (i.e. when
considered as a set of logical assertions, they include a transitivity
rule and one asserting a parent can't be a child of its child, plus a
consistency check)

This gives us a nice logical construct with general applicability.

We can then think about leveraging hierarchy in a dispatch mechanism.
Using a hierarchical system in dispatch matching means we can inherit
behavior, and, within a lineage, ensures a logical precedence due to
the, well, linear nature of lineages. Multiple inheritance is also not
a problem, as separate multimethods can be defined on separate trees
without conflict or ambiguity.

It is only when you have defined methods of the same multimethod on
two independent paths to the same child that things cannot be
logically resolved. This is something you should do only with great
reluctance, as it represents a true logical ambiguity, e.g. you've
said animals aren't allowed in the street, but transportation is, and
a horse is both. I still contend you'll encounter it most frequently
when trying to incorporate existing Java hierarchies. If you find you
need it frequently other than in that case, you have a sloppy design
IMO.

A monotonic ordering of the entire graph is not an essential property
of a hierarchy, in fact, I think it is more of a crutch than a
feature. Making logical ambiguities go away mechanically only
encourages more ambiguity and brittleness in the dependencies on the
mechanical resolution.

So, when there's an ambiguity we can always define a specific method,
and usually should. Being lazy, we also have prefer-method to resolve
it in favor of one inherited method, at the point we have the facts
about the particular ambiguity, and differently for each method if we
desire.

Here are the areas I'm looking to improve:

- There's no easy way to talk about "the method you would get if you
were dispatch value X". Note that this is not the same as call-next-
method, which reintroduces global ordering requirements, but allows
for easy explicit reuse of already-defined methods.

- Currently, a preference doesn't encompass the path through the
preferred value to its ancestors, but could.

- If you have a set of common preferences, there's no easy way to
create them in advance and share them among methods. There are issues
here related to ensuring preference consistency and caching.

Can we please move forward in trying to implement something better
than CLOS GFs? I have no interest in going backwards.

Rich

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to