Larry Wall wrote:
On Wed, Mar 16, 2005 at 11:49:12PM -0600, Rod Adams wrote:
: I haven't gotten a solid answer on when and how Perl will autogenerate : methods from subs.
In general I don't think of it as autogeneration at all, but as
failover to a different dispatcher. I can't think of a case where an
ordinary sub implies an ordinary method or an ordinary method implies
an ordinary sub. Multi subs can live in both worlds simultaneously
when they're defined within a class, but in that case it's a single
definition that is visible to both dispatchers. There may end up being
some hanky-panky of an autogeneration nature going on to optimize the
more common failover cases, and we've cut ourselves a little slack in
how we handle single argument functions and/or argumentless methods,
but by and large we should just be able to get away with a single
MMD definition for most purposes, and separate definitions where the
valence actually changes.
Okay, I'm now in the process of going through what I'd written of S29 to take this into account.
First up was
multi sub abs (: Num ?$x = $CALLER::_ ) returns Num
Which I presently have in Math::Basic. I could easily see someone wanting to do
my Num $x = -12.4; $x.=abs;
Which would suggest I need to add something that looks like:
multi sub Num::abs (Num $x) returns Num
Which I think means that I have two write a method version for every function that takes a $_ default, since the optional parameter happens after the colon, and therefore isn't part of the invocant. I'm fine with writing them double, I just want to be sure it's necessary.
: For instance, would
: : @array.grep(/foo/);
: : generate a call to the list op C<grep> above, or do I need to be : defining another form of C<grep> that's more agreeable to : autogeneration? If so, what makes a sub more agreeable to auto method : generation?
Well, grep is one of those cases where you really need two different definitions because you have conflicting invocants. If within the Array class you write a multi sub like this:
multi sub grep (Array @array, Selector $for) {...}
then it can be called either as @array.grep(/foo/) or
grep(@array,/foo/), but never as grep(/foo/,@array).
For C<grep> I now have:
multi sub Perl6::Array::grep (@values : Code *&test) returns Lazy
multi sub Perl6::Array::grep (@values, Any|Junction $test) returns Lazy
multi sub Perl6::Lists::grep (Any|Junction $test : [EMAIL PROTECTED]) returns Lazy
Does that look about right?
-- Rod Adams