@Larry,
I have been reading up on method resolution orders and class precedence
lists and all sort of meta-model esoteria. Which brings me to ask
myself, "How should all this be done in Perl 6?".
The current state of the prototype meta-model is that it only supports
pre-order class traversal (like Perl 5). However we are not limited to
this, the framework needed to support other traversal methods is now in
place.
Basically in order to implement submethods as described by Larry
(having an implicit "next METHOD if $?SELF != $?CLASS" in front of it),
I needed to implement a stateful dispatcher. This made it very easy to
then implement WALKMETH and WALKCLASS, which the metamodel now uses for
dispatching, and then to also make 'next METHOD' (implemented as
next_METHOD() in the prototype).
So this brings me to some questions regarding various traversal methods
listed in A12, they are:
:canonical # canonical dispatch order
:ascendant # most-derived first, like destruction order
:descendant # least-derived first, like construction order
:preorder # like Perl 5 dispatch
:breadth # like multimethod dispatch
My first question is, how is the dispatch order changed? I assume it is
through the %opt argument in WALKMETH and WALKCLASS.
My second question is, who would really be changing this? Is this
something Perl 6 will utilize internally? Will other things be
implemented which require these different traversal orders? Basically,
what good is having all these different traversal orders?
And lastly I have questions on each particular ordering.
- canonical
What would be considered the "canonical" method dispatch? I would
assume it would mean the traditional Perl 5 style (pre-order).
- preorder
Is this not the canonical way in Perl?
- breadth
I can see the usefulness of this if you are going to handle your own
WALKMETH, but wouldn't CALLONE, CALLALL handle this same behavior? Or
maybe I am not understanding its usefulness.
- ascendant/descendant
These two are the tricky ones, especially with multiple inheritance.
But thankfully there is much work already done on this subject, and all
we need to do is pick the one we like and copy... uh *ahem* borrow ...
it :)
So my question is this, given the following class layout:
A Least derived
/ \
B C
| |
D E
\ /
F Most Derived
What is the method resolution order (for ascendant order)?
F, D, E, B, C, A
or
F, D, B, E, C, A
The first one would follow a "strict" most-derived order, but will
probably not be what the user will expect. It also looks a lot like
breadth first traversal.
The second one is what all the other "cool kids" seem to be doing. It
is called "Monotonic Superclass Linearization" or "C3" and it is what
Guido and the boys are doing for Python 2.3. The original paper is on
the language Dylan
(http://www.webcom.com/haahr/dylan/linearization-oopsla96.html) and
gives a pretty good explaination. And it is detailed again in this
paper on python (http://www.python.org/2.3/mro.html). If you read both
of these papers (even just skimming them) you will see that this
approach makes a lot of sense. However it does impose some restrictions
on funky MI class composition which we would need to deal with.
Basically it should blow up in certain cases where the method cannot
properly be resolved no matter what (the papers give several examples
of this).
Personally I would go with the second one. It seems to "feel right" to
me, and I like anything which blows up in the face of overwhelming
ambiguity :)
I wonder too if we choose to use C3, then if that should not become the
canonical way?
Thanks,
Stevan