Re: MMD as an object.

2005-03-11 Thread Leopold Toetsch
Bob Rogers [EMAIL PROTECTED] wrote:
From: Leopold Toetsch [EMAIL PROTECTED]

1) is there a MultiSub object with one short name that holds all
possible long names (and function references)?
If yes, who is creating it: the Perl6 compiler emits code to do so or
it's up to Parrot to do the right thing?

 FWIW, Common Lisp specifies a generic function [1] that collects all
 methods defined for a given operation name.  (In Perl/Parrot, the
 generic function name for your examples would be the string foo; in
 Lisp, it would be the symbol FOO in some package, but the practical
 difference should be slight.)  The important thing is that the GF has
 all the information required to make method dispatch decisions.

That sounds exactly like the MultiSub object that gathers a candidate
list of all subroutines with the same short name.

 ... But on the other hand, the CL community has
 more than 15 years of experience with MMD, so I wanted to be sure
 everyone was aware of it.

Yeah, that's really helpful.

2) namespaces of (multi) subs.

A non-multi method is in the classes' namespace. In Parrot terms that's
currently:

  %globals{\0class_name}{method_name}

I'm not quite sure, if the method hash shouldn't live inside the class.

 Is naming at this level really important here?

Well, the short name of the multi sub has to be stored somewhere.

 ... The operation itself
 needs a name (so that people can call it), and classes need class names
 (maybe), but all methods are implicitly named by the combination of
 operation plus argument signature.

Yes. That's the long name in Perl6 design documents.

 ... Which would seem to mean that,
 unlike perl5, the package in which a multimethod is defined doesn't
 matter; all that is captured by the argument signature.

Yep. You can define a multi sub anywhere.

 ... Or is it
 possible to have more than one method with the identical signature?  And
 if so, what does that mean?

There can be identical signatures in different scopes. Within one scope,
I don't know.

The long name is therefore a list of class names, which suggests
 that the single-dispatch naming above is backwards.  Of course, I'm
 probably out of my depth here . . .

The long name contains the signature. The short name is the bare
foo.

A multi method is similar, except that their can be more then one
with the same short name (which probably means that there has to be a
MultiSub object holding the long names)

 I'm not sure it is meaningful to give a sub a short name,

You call it by the short name.

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

 This sounds right to me.  Or perhaps

   %globals{foo}  --  MultiSub{[foo, 'A', 'B'] = Sub, ...}

Yep, something like that.

 just to belabor the point a bit.

What about a not so global multi:

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

Thanks for clarifying,
leo

 Is this really different?  After all, the operation foo should be just
 a string in either case.

Sure. But the string foo has to live in some namespace. But, it it's
not marked as global it's probably in either a package or a module, so
again it has it's namespace.

   -- Bob Rogers

leo


Re: MMD as an object.

2005-03-11 Thread Leopold Toetsch
Rod Adams [EMAIL PROTECTED] wrote:

 Leopold Toetsch wrote:

Discussion seems to have went off into esoteric cases of locally
overriden dispatcher policies and what not.

 I don't think it's as esoteric as you might think. Consider:

 package Foo;

 use MMD::Random;
 our bar is MMD::Random is export(DEFAULT);

 multi sub bar ($x) {...};
 multi sub bar ($x) {...};

 Note that they all have the same signature. The Manhattan policy would
 complain about this, since it's looking for the closest parameter match.
 The Random policy does not care. It's going to randomly pick any member
 method for each call.

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 :)

 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. You have
all methods and information to be able to do your own dispatch, if
needed. Your approach would very likely disable all possible
optimizations.

Anyway, that's far future.

What I'd like to know is more basic things:

Yes, still :-)

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.

 Even without custom policies, p6c may decide to go the MultiSub object
 route at the compiler level. But I can't speak to that, nor on the
 Compiler - Parrot interaction.

It depends on what Parrot will get from the Perl6 compiler.

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.

 However if you have multi's from a mix of different sources and scopes,
 all with the same short name, which policy decides how to dispatch
 amongst them at a given calling locality is very much at issue, and is
 roughly where we are in the discussion.

Yes. The policy will be handled by a dispatcher object's dispatch
vtable, as far as I can currently see.

leo


Re: MMD as an object.

2005-03-11 Thread Miroslav Silovic
[EMAIL PROTECTED] 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);
 

This is enough to make me completely happy. :)
   Miro


Re: MMD as an object.

2005-03-11 Thread Rod Adams
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 

Re: MMD as an object.

2005-03-11 Thread Leopold Toetsch
Rod Adams [EMAIL PROTECTED] wrote:

 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.

Not necessarily, AFAIK. You can define a lexical sub bar, which hides
all outer multi subs. This bar can be used to dispatch to the multi
subs.

 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...

Well, I presume, if you are writing such code, i.e. a bunch of mutli
subs with the same signature, you are very well aware of what you are
doing. So you'll know, how you call the dispatcher (and what funny
effects you'll yield :)

... 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.

I don't thing that the MultiSub does dispatch nor that it has a dispatch
method. The MultiSub object is just a collection of multi Sub candidates
for one of the scopes [lexical, package/module/class, global, builtin].

The current dispatcher has to collect a list of possible candidates from
all the possible multis, and then decide, depending on the policy, which
sub should actually be called.

 3) It does not allow more than one sub with the same signature and short
 name to be in scope at the same time.

That's mainly a Perl6 compiler problem. When the MultiSub is just a list
of candidates, you can append whatever signature you like. There is no
check for duplicates. It's only the dispatcher that will detect
ambiguous signatures, if it cares about, like the default dispatcher.

 ... For instance, dispatching based on return
 type.

Well, while there is a symmetry in call and return, when Parrot is
concerned, dispatching on return types isn't easy, or better, it could
just be done for the total static case, where all return results are
known beforehand. For that case you could just call different subs in
the first case.
If the return type is just the runtime result, after the sub is run, you
can do nothing in the dispatcher, which long before had called the sub.

 ... Or off of some user defined trait the different methods have. Or
 the most common case: on named arguments.

A trait creates usually an anonymous subclass of the involved class and
therefore has precedence over a not so specific class.

MMD on named arguments isn't specified yet, or:

,--[ A12 ]
| It is not likely that Perl 6.0.0 will support multiple dispatch 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.

As said, that's mainly a Perl6 compiler problem. The compiler can't emit
two identical long names as one of these wouldn't be callabale then.

 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.

What policy is in effect, if you define somewhere a multi sub? I
think, that can't work.

 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.

No, I don't think so. The current (lexical) scope has the policy,
according to A12.

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

[ good questions for the compiler folks ]

leo


Re: MMD as an object.

2005-03-11 Thread Rod Adams
Leopold Toetsch wrote:
Rod Adams [EMAIL PROTECTED] wrote:
 

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.
   

Not necessarily, AFAIK. You can define a lexical sub bar, which hides
all outer multi subs. This bar can be used to dispatch to the multi
subs.
 

I sounds like a good plan, as long as it works. However, I'd want to 
create the sub at the same scope (most likely class/package) as the 
multi subs with the same name. I'm presently not clear if that's 
allowable. If I have to create a lexical method in each user to dispatch 
to my class, that seems sub optimal. I prefer to stick with .bar vs ._bar

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...
   

Well, I presume, if you are writing such code, i.e. a bunch of mutli
subs with the same signature, you are very well aware of what you are
doing. So you'll know, how you call the dispatcher (and what funny
effects you'll yield :)
 

Consider the case where I wish to create several multi's with 
significantly different signatures, but you write each one twice, once 
with an is debug trait, and once with an is operational trait. I 
would have some runtime signal to determine if I need to be running the 
debug versions, or the operational versions.

If you put too much onus on the caller function to get the call correct, 
you might as well just name all the methods something different and 
forget about MMD altogether.

... 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.
   

I don't thing that the MultiSub does dispatch nor that it has a dispatch
method. The MultiSub object is just a collection of multi Sub candidates
for one of the scopes [lexical, package/module/class, global, builtin].
 

Currently you are likely correct. I was proposing to change that.
The current dispatcher has to collect a list of possible candidates from
all the possible multis, and then decide, depending on the policy, which
sub should actually be called.
 

I was offering the ability to change which policy does the decisions, 
after collecting the candidates.

3) It does not allow more than one sub with the same signature and short
name to be in scope at the same time.
   

That's mainly a Perl6 compiler problem. When the MultiSub is just a list
of candidates, you can append whatever signature you like. There is no
check for duplicates. It's only the dispatcher that will detect
ambiguous signatures, if it cares about, like the default dispatcher.
 

So you're saying that if I create a multi with the same scope and long 
name as a preexisting multi, that old multi will still be around in 
memory, even though it could never be called without a custom dispatcher?

I was under the impression that defining two multi's with the same long 
name in the same scope clobbered one of the involved parties and 
triggered a redefinition warning.

... For instance, dispatching based on return
type.
   

Well, while there is a symmetry in call and return, when Parrot is
concerned, dispatching on return types isn't easy, or better, it could
just be done for the total static case, where all return results are
known beforehand. For that case you could just call different subs in
the first case.
 

I was imagining dispatching based off the C want  function, which I 
have no idea how it will be implemented at the Parrot level, but it's a 
defined part of Perl.

If the return type is just the runtime result, after the sub is run, you
can do nothing in the dispatcher, which long before had called the sub.
 

Of course.
 

... Or off of some user defined trait the different methods have. Or
the most common case: on named arguments.
   

A trait creates usually an anonymous subclass of the involved class and
therefore has precedence over a not so specific class.
 

A trait added to an object instance creates an anonymous subclass, 
certainly.
But I didn't think that adding a trait to a member of a class created a 
new subclass...

MMD on named arguments isn't specified yet, or:
,--[ A12 ]
| It is not likely that Perl 6.0.0 will support multiple dispatch on named
| arguments,
`-
 

Indeed, that is the current case.
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

Re: MMD as an object.

2005-03-10 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
It would behave like a tied sub (or method), with a .dispatch method 
to decide which of the contained routines should be called this 
particular time. Manhattan would be the default. However, one can 
override the dispatch logic; implementing Luke's Patterns idea, for 
example.

Hmm, that ties into my wishlist item. Would it be possible to implement 
method combinators (or rather, multimethod combinators) from Common LISP 
in addition to this? The only CLOS feature that A12 doesn't mention, 
can't let that happen. ;)

class A { ... }
class B is A { ... }
1 multi foo ($a) is before { ... }
2 multi foo (B $a) { ... next METHOD; ...}
3 multi foo (A $a) { ... }
4 multi foo ($a) is after { ... }
5 multi foo ($a) is around { ... next METHOD; }
6 multi foo ($a) is before { ... }
 and this runs all 5 methods, in order 5  1  2  6  3  (returns 
to 2)  4  (returns to 5)
And yes, 6 and 1 do have the same signature. The rule is to run all 
before methods in order of the currently selected distance (ties broken 
in random order ;) ), and all after methods in the reverse order.

Oh, and the reason why around methods are useful?
multi foo ($a) is around {
   CATCH { ... }
   next METHOD;
}
Note that this catches the exceptions thrown by any version of foo, even 
though at this point you don't know whether foo will be specialised. 
before methods aren't useful for this since their stack frame and 
handler blocks don't linger during the executions of other methods.

Common LISP references:
Standard method combination (before, after, around)
http://www.lispworks.com/documentation/HyperSpec/Body/07_ffb.htm
Other method combinations (+, and, etc)
http://www.lispworks.com/documentation/HyperSpec/Body/07_ffd.htm
Creating your own method combinations (define-method-combination)
http://www.lispworks.com/documentation/HyperSpec/Body/m_defi_4.htm
Come to think of this, it seems that the only thing that'd need to be 
modified to accomodate both Rod's and mine proposal is to move CALLONE 
and CALLALL from the class to be MMD object somehow. Perhaps

multi CALLONE ($obj, $method where { $_ == func }, [EMAIL PROTECTED]) { ... }
Hmm, but this syntax strikes me as icky.
   Miro


Re: MMD as an object.

2005-03-10 Thread Leopold Toetsch
Rod Adams [EMAIL PROTECTED] wrote:
 It seems to me that there are several advantages to making a group of
 multi with the same short name a single object, of type
 MultiSub|MultiMethod, which internally holds references to the all the
 various routines that share that short name.

Discussion seems to have went off into esoteric cases of locally
overriden dispatcher policies and what not.

What I'd like to know is more basic things:

1) is there a MultiSub object with one short name that holds all
possible long names (and function references)?
If yes, who is creating it: the Perl6 compiler emits code to do so or
it's up to Parrot to do the right thing?

2) namespaces of (multi) subs.

A non-multi method is in the classes' namespace. In Parrot terms that's
currently:

  %globals{\0class_name}{method_name}

I'm not quite sure, if the method hash shouldn't live inside the class.

A multi method is similar, except that their can be more then one
with the same short name (which probably means that there has to be a
MultiSub object holding the long names)

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) {...}

Thanks for clarifying,
leo


Re: MMD as an object.

2005-03-10 Thread David Storrs
On Wed, Mar 09, 2005 at 03:38:52PM -0600, Rod Adams wrote:

 There lingers the case of:
   
use Foo; # from above, exports bar is MMD::Random
 
multi sub bar {...}
 
 Does this generate an error, since one could expect this particular bar 
 to be Manhattan? Or does it assume Random, since there's already a bar 
 in existence? In my head, it currently makes sense to say that the new 
 bar inherits the Random policy. Only something like:

This seems like action-at-a-distance to me; I use some random module,
define a couple of multis without realizing that they also exist in
the module, and am baffled as to why I don't get the dispatch behavior
I expect.

--Dks


Re: MMD as an object.

2005-03-10 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
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) {...}
Thanks for clarifying,
leo
 

Uh, the real problem is the interaction between multisubs and modules. 
If you import a multi with the same short name from another module, you 
get a real issue that needs resolving. Especially if they do 
fundamentally different things and you don't expect a clash. Like

module Users;
multi get(Stream $f, UserDescriptor $u) {...}
...
module FileTransfer;
multi get(Server $s, File $f) {...}
Even if this is easy to fix by renaming, the error message would take a 
while to track down and it'd be annoying distraction during development. 
I believe the DWIM thing to do would be to merge multis into the same 
MMD object on module load. This would have to happen during runtime, 
since that's when the module load can occur.

   Miro


Re: MMD as an object.

2005-03-10 Thread Rod Adams
David Storrs wrote:
On Wed, Mar 09, 2005 at 03:38:52PM -0600, Rod Adams wrote:
 

There lingers the case of:
 
  use Foo; # from above, exports bar is MMD::Random

  multi sub bar {...}
Does this generate an error, since one could expect this particular bar 
to be Manhattan? Or does it assume Random, since there's already a bar 
in existence? In my head, it currently makes sense to say that the new 
bar inherits the Random policy. Only something like:
   

This seems like action-at-a-distance to me; I use some random module,
define a couple of multis without realizing that they also exist in
the module, and am baffled as to why I don't get the dispatch behavior
I expect.
 

Well, if you were not expecting Foo to export some bar's, then you're 
in for a surprise regardless of dispatch when you call bar in your code 
and one of Foo::bar gets called instead of one of yours, because it was 
a closer match.

I would say that people should know what they are getting into when they 
C use  something. In Perl 6, that use could conviently swap the 
meanings of all the + and - signs, and not say a word. In my head, this 
extends to knowing what it exports, and if there's anything weird about it.

If I am consciously adding more multi's into something a package 
provided, to extend it's functionality, I would think that keeping the 
original dispatch system would make sense. Otherwise  the imported 
methods could fail to work properly.

-- Rod Adams



Re: MMD as an object.

2005-03-10 Thread Rod Adams
Leopold Toetsch wrote:
Rod Adams [EMAIL PROTECTED] wrote:
 

It seems to me that there are several advantages to making a group of
multi with the same short name a single object, of type
MultiSub|MultiMethod, which internally holds references to the all the
various routines that share that short name.
   

Discussion seems to have went off into esoteric cases of locally
overriden dispatcher policies and what not.
 

I don't think it's as esoteric as you might think. Consider:
   package Foo;
   use MMD::Random;
   our bar is MMD::Random is export(DEFAULT);
   multi sub bar ($x) {...};
   multi sub bar ($x) {...};
   multi sub bar ($x) {...};
 
   ==

   use Foo;
  
   multi sub bar ($x) {...};

Note that they all have the same signature. The Manhattan policy would 
complain about this, since it's looking for the closest parameter match. 
The Random policy does not care. It's going to randomly pick any member 
method for each call.

So what we then fall into is the problem of which policy is in effect 
for a given multi can affect what's in scope at a given point. If the 
later file included:

   sub baz {
 my multi sub bar ($x) {...};
 bar(5);
   }
A Manhattan policy would have the local bar mask the package bar with 
the same signature. A Random policy would temporarily add it into the mix.

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.

What I'd like to know is more basic things:
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.

Even without custom policies, p6c may decide to go the MultiSub object 
route at the compiler level. But I can't speak to that, nor on the 
Compiler - Parrot interaction.

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.  Method dispatch 
has a similar issue with hunting down all the C isa s for possible 
method's to include in dispatch. So far, I think this issue has been 
politely ignored as p6c's problem, not p6l's.

However if you have multi's from a mix of different sources and scopes, 
all with the same short name, which policy decides how to dispatch 
amongst them at a given calling locality is very much at issue, and is 
roughly where we are in the discussion.

Thanks for clarifying,
 

Sorry I couldn't clarify more.
-- Rod Adams


Re: MMD as an object.

2005-03-10 Thread David Storrs
On Thu, Mar 10, 2005 at 02:22:20PM -0600, Rod Adams wrote:
 David Storrs wrote:
 On Wed, Mar 09, 2005 at 03:38:52PM -0600, Rod Adams wrote:
   use Foo; # from above, exports bar is MMD::Random
   multi sub bar {...}
 
 Does this generate an error, since one could expect this particular bar 
 to be Manhattan? Or does it assume Random, since there's already a bar 
 in existence? 
 
 This seems like action-at-a-distance to me; 
 
 Well, if you were not expecting Foo to export some bar's, then you're 
 in for a surprise regardless of dispatch when you call bar in your code 
 and one of Foo::bar gets called instead of one of yours, because it was 
 a closer match.
 
 I would say that people should know what they are getting into when they 
 C use  something. 


What I'm hearing you say here is Yes, it's action-at-a-distance, but
it's your job to make sure it doesn't trip you up.  The problem that
I see is that I may well be able to keep track of everything from the
modules I import, but what about the ones THEY import...and the ones
THEY import...and so on.  In a medium-to-large software project, that
can get to be a lot of modules, very quickly.

--Dks


Re: MMD as an object.

2005-03-09 Thread Thomas Sandlaß
Rod Adams wrote:
It seems to me that there are several advantages to making a group of 
multi with the same short name a single object, of type 
MultiSub|MultiMethod, which internally holds references to the all the 
various routines that share that short name.
It doesn't have to be junctive because for a multi it's irrelevant
if it's a method or a sub. This distinction is used only at compile
time of the class closure. So I guess there is a
class Multi is Code {...}
in Perl 6.

It would behave like a tied sub (or method), with a .dispatch method to 
decide which of the contained routines should be called this particular 
time. Manhattan would be the default. However, one can override the 
dispatch logic; implementing Luke's Patterns idea, for example.
I see. Something like
use MMD::Manhattan;
use MMD::Symmetric;
use MMD::Pattern;
...
 [..] I don't think there has
been syntax introduced thus far that enables this ability. But it's 
likely I missed it along the way, like I seem to be missing several 
other things lately.
I interpret the hash like syntax fooInt,Array[Int] such that
foo represents the complete set of branches of multi sub foo.
The only thing I wonder is this also supported for calling particular
subs without dispatching: fooInt(17)? Or even partial dispatching
on the sliced multi? This would BTW be something the optimizer would
use as well.

Another thing I haven't seen is how to declare a new multi at runtime. 
Non-multi's can be created via C func := sub {...}; , but that's 
destructive to any other routines that might have occupied that 
namespace.
If the above is correct than it would be more like hash assignment.

There are likely several rough edges in here, and I've by no means 
convinced myself that this is the Right Thing, but I thought I'd throw 
the idea out there to what others thought of it.
I see some convergence and choices where that is not the case.
MfG
--
TSa (Thomas Sandlaß)



Re: MMD as an object.

2005-03-09 Thread Rod Adams
Thomas Sandlaß wrote:
Rod Adams wrote:
It seems to me that there are several advantages to making a group of 
multi with the same short name a single object, of type 
MultiSub|MultiMethod, which internally holds references to the all 
the various routines that share that short name.

It doesn't have to be junctive because for a multi it's irrelevant
if it's a method or a sub. This distinction is used only at compile
time of the class closure. So I guess there is a
class Multi is Code {...}
in Perl 6.
I wasn't intending it to be junctive. I was just noting that you needed 
separate holders for subs and methods, since you shouldn't be able to 
stuff a method into a multi sub.


It would behave like a tied sub (or method), with a .dispatch method 
to decide which of the contained routines should be called this 
particular time. Manhattan would be the default. However, one can 
override the dispatch logic; implementing Luke's Patterns idea, for 
example.

I see. Something like
use MMD::Manhattan;
use MMD::Symmetric;
use MMD::Pattern;
...
I was thinking more along the lines of :
   use MMD::Pattern;
   our func is MMD::Pattern;
   multi func (...) {...}
   multi func (... ...) {...}
   multi func (... ... ...) {...}
   multi func2 (...) {...}
   multi func2 (... ...) {...}
   multi func2 (... ... ...) {...}
Where func would get Pattern MMD, and func2 would get Manhattan MMD.
-- Rod Adams


Re: MMD as an object.

2005-03-09 Thread Luke Palmer
Rod Adams writes:
 I wasn't intending it to be junctive. I was just noting that you needed 
 separate holders for subs and methods, since you shouldn't be able to 
 stuff a method into a multi sub.

Keep in mind that the two following definitions are equivalent:

class A { method foo () {...} }
multi sub foo (A $a) {...}

I think stuffing a method into a multi sub should be just fine.

Luke


Re: MMD as an object.

2005-03-09 Thread Thomas Sandlaß
Luke Palmer wrote:
Keep in mind that the two following definitions are equivalent:
class A { method foo () {...} }
multi sub foo (A $a) {...}
Except for attribute access, I think.
For public attrs the accessor is not used and private ones are available:
class A
{
   has $.pub = pub;
   has $:priv = priv;
   method foo ()
   {
  say pub = $.pub;
  say priv = $:priv;
   }
}
multi sub foo( A $a )
{
   say pub = $a.pub();
}
Another subtlety is that the method call syntax prefers single dispatch:
my $obj = A.new;
$obj.foo();
foo( $obj );

I think stuffing a method into a multi sub should be just fine.
Me too. The above is irrelevant for the call site.
MfG
--
TSa (Thomas Sandla)



Re: MMD as an object.

2005-03-09 Thread Larry Wall
On Wed, Mar 09, 2005 at 06:19:25AM -0600, Rod Adams wrote:
: I was thinking more along the lines of :
: 
:use MMD::Pattern;
: 
:our func is MMD::Pattern;
: 
:multi func (...) {...}
:multi func (... ...) {...}
:multi func (... ... ...) {...}
: 
:multi func2 (...) {...}
:multi func2 (... ...) {...}
:multi func2 (... ... ...) {...}
: 
: Where func would get Pattern MMD, and func2 would get Manhattan MMD.

Might be better to define some modifiers other than multi just for the
documentation value, if you're going to have different policies in the
same file like that.  I expect that's a rarity, though.  Most files
would have a single MMD policy.

But the main problem I see with all this is that MMD is supposedly
combining short names from potentially many different scopes across
*multiple* files, and what do you do if those have different policies?
Plus the OP assumed that all instances of a particular short name are
represented by a single object, which is not necessarily the case,
since different lexical scopes can see different (and potentially
overlapping) sets of multis with the same short name.  I suppose one
could get around that by placing an implicit constraint on multis
you're not supposed to be able to see, though.  Except that you really
need unique long names as well within one of these objects, and two
completely distinct lexical scopes could have long names that would
be confused with each other.  Oh wait, the lexical scope constraint
would be part of the long name, just like any other constraint.
Nevermind.  Though maybe you still want to have separate objects
since it's a performance hit to actually evaluate constraints at
run time.

But we still have the problem of conflicting policies in different
scopes.  Maybe it's not a problem if we view different policies as just
different ways of marking autogenerated signatures with distance, if
we can come up with a single underlying *scalar* distance measure that
different policies can map multidimensional distances to differently.
Some policies might only choose between 0 and Inf for the scalar
distance, for instance, while others might try to finesse additional
distance values.  It seems to me that both the manhattan scheme and
the pure scheme can be subsumed under that, but I could be wrong.

Larry


Re: MMD as an object.

2005-03-09 Thread Rod Adams
Larry Wall wrote:
On Wed, Mar 09, 2005 at 06:19:25AM -0600, Rod Adams wrote:
: I was thinking more along the lines of :
: 
:use MMD::Pattern;
: 
:our func is MMD::Pattern;
: 
:multi func (...) {...}
:multi func (... ...) {...}
:multi func (... ... ...) {...}
: 
:multi func2 (...) {...}
:multi func2 (... ...) {...}
:multi func2 (... ... ...) {...}
: 
: Where func would get Pattern MMD, and func2 would get Manhattan MMD.

Might be better to define some modifiers other than multi just for the
documentation value, if you're going to have different policies in the
same file like that.  I expect that's a rarity, though.  Most files
would have a single MMD policy.
 

Well, my intent was that one should be assigning the policy to a given 
multi, not a given scope. If people wish to change the default policy 
for multis defined in a given scope, I have no problems with that.

The reason for binding the policy to a given multi was so people could 
write a package Foo with a pack of multi sub bar's,  using policy 
MMD::Random, and export into a different scope, but still have the 
caller use the Random policy when calling bar.

But the main problem I see with all this is that MMD is supposedly
combining short names from potentially many different scopes across
*multiple* files, and what do you do if those have different policies?
Plus the OP assumed that all instances of a particular short name are
represented by a single object, which is not necessarily the case,
since different lexical scopes can see different (and potentially
overlapping) sets of multis with the same short name.  I suppose one
could get around that by placing an implicit constraint on multis
you're not supposed to be able to see, though.  Except that you really
need unique long names as well within one of these objects, and two
completely distinct lexical scopes could have long names that would
be confused with each other.  Oh wait, the lexical scope constraint
would be part of the long name, just like any other constraint.
Nevermind.  Though maybe you still want to have separate objects
since it's a performance hit to actually evaluate constraints at
run time.
I'm going to interpret this as This is a solvable problem that just 
needs a little optimization in the compiler.
Please correct me if this a poor interpretation.

But we still have the problem of conflicting policies in different
scopes.  Maybe it's not a problem if we view different policies as just
different ways of marking autogenerated signatures with distance, if
we can come up with a single underlying *scalar* distance measure that
different policies can map multidimensional distances to differently.
Some policies might only choose between 0 and Inf for the scalar
distance, for instance, while others might try to finesse additional
distance values.  It seems to me that both the manhattan scheme and
the pure scheme can be subsumed under that, but I could be wrong.
 

The problem with this is that it requires people to be very cooperative 
with how they assign their scalar values. And that feels like asking for 
trouble.

I think a better solution is to make it where a given short name can 
only have one policy. Trying to assign two policies to the same multi 
would be a warning at least, and preferably an error.

There lingers the case of:
  
   use Foo; # from above, exports bar is MMD::Random

   multi sub bar {...}
Does this generate an error, since one could expect this particular bar 
to be Manhattan? Or does it assume Random, since there's already a bar 
in existence? In my head, it currently makes sense to say that the new 
bar inherits the Random policy. Only something like:

   use Foo;
   our bar is MMD::Manhattan;
   multi sub bar {...}
Would trigger an error.
-- Rod Adams