Leopold Toetsch wrote:

Ok. If you'd really need such random dispatch, it could be done like
this, when I interpret A12 correctly:

 sub run_random_bar($x) {
    my @meths = WALKMETH($x, :method('bar'));
    my $meth = @meths[rand(@meths.elems)];
    $meth($x);
 }

or even with

 my sub bar($x) {...} # same body as above

 bar($x);

If you need an esoteric dispatcher roll your own :)


That's certainly the doable with any language that provides sufficient introspection, within limits. It's a matter of where you store your hand rolled dispatcher.

If I were to need a different policy for a given method .bar, I would likely create something called .bar much like your "run_random_bar", which then dispatches amongst methods I name something like ._bar .

I see some detractions to this approach:
1) Users wishing to add another multi to the mix must know that they have to make it a ._bar instead of a .bar. This is a relatively minor concern. It feels rather clumsy having two different names for what is essentially a single set of multis.


2) What parameter signature do you give the wrapper method, so it does not clobber the arguments, yet still has them to pass on to the appropriate method? And at the same time, determine what signature the wrapper was called with, to determine who to dispatch to... I hadn't said it before, but I had assumed the dispatch method of the MultiSub would have a signature of something like "Str @types" passed to it.

3) It does not allow more than one sub with the same signature and short name to be in scope at the same time. There are cases more legitimate than MMD::Random for this. For instance, dispatching based on return type. Or off of some user defined trait the different methods have. Or the most common case: on named arguments.

My understanding of the P6 Long Names is that if one creates a multi with the same parameter signature as a previously defined multi of same short name, it masks the previous one if in a tighter scope, or erases the previous if the same scope.

The original thought was to have the policy take over the acceptance of new multi's into the MultiSub as well as taking over dispatch, thus allowing for such flexibilities.


Since the main goal of treating multis as an object was to be able to
override the dispatch policy, I think how a user defined policy
interacts with different localities is very much on topic.



I don't think that the policy should be in the MultiSub object.

I'm not sure if I think it should be there either. It just seemed to allow some flexibility in having it there that is otherwise very difficult to do.

And quite likely, the policy itself would not be in the MultiSub, but the MultiSub would have a reference to which policy it's using.

Your approach would very likely disable all possible optimizations.


It's always been in the back of my head that this would be a performance hit. How big of one I don't have a good feel for. I've been attempting to get a feel for how much is gained in return for that hit. So far I am inclined to agree that the benefits do not outweigh the costs, but I like to know exactly what I'm giving up when making those decisions.

1) is there a MultiSub object with one short name that holds all
possible long names (and function references)?


As for whether such a thing is visible at the Perl level, I think that
depends on if we allow user defined dispatch policies or not. If not,
it's just an introspection tool that could be addressed in other ways.



Don't think so. It's a problem of namespaces and how these multi subs
are managed. It touches Perl6 as well as Parrot.


What I meant to say was that yes, there does need to be management and introspection capabilities at the Perl6 level, but they do not *require* it to be a MultiSub object to happen. Some non-object solution could likely be found.

With that mindset, the compiler could use a PMC object for it, but show the Language something else, or it could show the Language something that looks like an object, but use something different in Parrot. Those are questions I am not able to answer.

Some of the management issues I see that need addressing are:

- How do I dynamically create a new multi with differing levels of scope? For instance, add a package scoped multi from inside a sub of that package?

- If I'm in a lexical scope which overrides a certain long name, how can I call the package scoped version of that long name instead?

- Given a method returned from WALKMETH, what scope level is it defined at?

- Can I get a CODEREF that points to the short name as a whole, or do I have to take a ref to a given multi?

- How can I tell if a given long name already exists?



What about multi subs? They can be defined everywhere. Given:

multi sub *foo(A $a, B $b) {...}

Is this something like:

%globals{"foo"}  -->  MultiSub{"foo_A_B" => Sub, ...}

What about a not so global multi:

multi sub foo(A $a, B $b) {...}




This can be seen as questioning how to keep track of what multi's are in
scope at any given point in time, because you must dispatch amongst all
the multi's visible, regardless of the differing scope.



Sure. But the dispatch scheme is described in A12. That is per se not
the problem.


Unless your proposal was to allow user defined changing of that scheme. Then it becomes a problem.


-- Rod Adams

PS - I stopped the cross posting to p6i, since I was asking more questions than answering, and those question didn't belong there.

Reply via email to