Front page | perl.perl6.internals |
Postings from July 2002
Re: vtables and multimethod dispatch
From: Dan Sugalski
July 11, 2002 11:10
Re: vtables and multimethod dispatch
Message ID: email@example.com
At 9:50 AM -0700 7/11/02, John Porter wrote:
>Dan Sugalski wrote:
>> lookup is O(n) since we precompute the dispatch table.
>Oh. So the cost of computing the table is amortized over all the
>mm calls that go to the table for resolution. Could be Bad,
>for the typical small Perl program.
More the cost of computing the table is relative to the number of
classes that insert multimethods, but yeah there is a cost for each
>Then there's the issue of the size of the table.
>Considering that, in the worst case (for fastest lookup time)
>the table is exponential in the number of types, this
>could be Bad.
There are ways to make the tables smaller. In the two-arg case we're
considering for PMCs specifically, it can be reduced to a
one-dimensional table bounded by the first and last type that has a
specific method specified.
So, if add for type 77 only has mm specified for types 1000 and 1001,
we can shrink the table to two elements with a start offset. That
trades space for speed, though, since lookups will be slightly slower.
>But clearly, for predefined types (e.g. I/N/S/P) and binary
>ops, a predefined table of size 16 isn't unreasonable.
>Ooh, but wait. There's also the issue that, in general, the
>*number of tables* is O(n) in the number of ops! Ouch!
>(But this is true regardless of the resolution method.
>Even if we used some kind of heuristic or "type dominance
>graph", there would O(nOps) of them.
>[Note, those should actually be Theta, but I'm not sure how
>to draw that portably.]
Well, the number of tables is relative to the number of potential
methods we allow to be multimethods. In general that's potentially
unbounded, but for the specific case of PMC vtable methods it's a
It gets more interesting for general methods and subs, but we can
deal with that a bit later.
> > We look for
>> the entry in the table based on the type of the left and right side.
>I would point out that the mm problem pertains to more than just
Sure, but for vtable methods we only care about the binary ops, since
we don't have any trinary ops, and the unary ops don't need mm
> > What we're really doing is left-side-wins always. It's just that, in
>> the case of all the perl types, they then do a multimethod lookup for
>> the ultimate routine to execute.
>Well then you're still left with a mm lookup problem.
>I think it's *this* mm resolution problem that we're talking about.
Yep. Luckily it's a bounded and relatively simple problem. :)
> > > In the example of int-vs-float, the rulebase (it's really just
> > > a DAG) decides that float wins. So a float.method gets an int
>> > argument; the int isn't promoted to a float.
>> Ah. In that case it's really a subset of multimethod dispatch,
>"a subset of"?
>It *is* multimethod dispatch, but for just a pre-defined
>subset of cases. Is that what you mean?
> > > > If we can't find a match, or ... no clear winner,
> > > > we throw an exception.
>> > You don't like the idea of falling back to left-side-wins?
>> Oh, I like it, but at that point we've already decided to do a MM
>> lookup, so there's really no going back.
>O.k., I agree that "if there is no clear winner" we should throw.
>But yet, it seems to me that "left side wins" is a resolution
>technique that always yields a clear winner, in which case we'd
If we did that, yes. Unfortunately while left side wins yields a
clear winner, it doesn't necessarily yield the correct winner. If we
a->b, and c->d
methods add(a, d) and add(b, c)
but are presented with add(b, d), then neither method is specifically
correct, and neither is really less correct than the other. In that
case, while LSW is a way to break the ties, it doesn't really break
them definitively correctly.
The right thing is to have a tiebreaker fallback method, one that we
call when we have no clear winner, even if that method is further
away in our n-dimensional space, and have it decide. The default
tiebreaker will just pitch an exception (which is a clue the
programmer should put in code to deal with the problem :) but it's
certainly valid for a class to install a different tiebreaker method,
and that may do LSW resolution. (In the example it'd dispatch to
"add(b,c)" since the left side is 'better' in that one)
That's the plan, at least. Plans, of course, are subject to change.
--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
firstname.lastname@example.org have teddy bears and even
teddy bears get drunk