> Right.  I believe the times one will want to do a method call on $_ when it
> is *not* the invocant will be greatly outnumbered by the times when you
> want to do a method call on the invocant.  Thus adding ambiguity to .method
> is not worth it.

I think this boils it all down nicely.  It seems more important to have 
consistency on what .method does.  I think it should stay bound to the 
invocant and should die/warn if there is none.  There are so many "almost" 
short ways to call methods on the current topic of grep or map that it seems 
a shame to mess up the consistency of .method just to remove a few 
characters.

Consider:

method foo {
         .do_one_thing
         .and_another_thing
         map { $_.do_something_with( .bar ) } .items;
         # .bar worked on the invocant - not the items
         .and_the_last_thing
}

method foo {
         .do_one_thing
         .and_another_thing
         map { $^item.do_something_with( .bar ) } .items;
         .and_the_last_thing
}

Both of those feel clean to me as opposed to

method foo {
         o.do_one_thing
         o.and_another_thing
         map { .do_something_with( o.bar ) } o.items;
         o.and_the_last_thing
}

Now granted - that the o. isn't the worst thing to look at.  It still seems 
harder to follow what is calling which method - you sort of have to deduce 
that since the do_something_with call doesn't begin o and because you are in 
a map then it must be behaving on the topic $_ even though $_ isn't in sight.  
We have added a nother level of details (arguably ambiguity) to try and clear 
up some ambiguity.

With the former methods it is clear and consistent which methods are being 
called on which variables.  The .method doesn't change mid method and I know
what variable is calling do_something_with because it is spelled out.

It seems that the "oc behavior" and the ".method acts on $_" are huffmanized 
the wrong direction.

Now with an object in non-method we have with .method only on invocant we 
have:

sub foo {
        my Foo $o = get_object();
         $o.do_one_thing
         $o.and_another_thing
         map { $_.do_something_with( $o.bar ) } $o.items;
         $o.and_the_last_thing
}

sub foo {
        map { .do_something_with() } get_items();
        # dies because there is no invocant
}

and with the .method uses $_ we have

sub foo {
        my Foo $o = get_object();
         $o.do_one_thing
         $o.and_another_thing
         map { .do_something_with( $o.bar ) } $o.items;
         $o.and_the_last_thing
}

We haven't really won anything other than dropping a few characters.

As I was thinking about that I began wondering if it was possible to 
dynamically specify what the invocant is.  Wouldn't you know it?  That is 
what $_ does  currently - except you only get .methods, not $.properties.

The more I think about it the more I think the current behavior of .method on 
$_ is wrong.  I don't think you should be able to dynamically set the 
invocant.  Consider the danger of:

method foo {
          some_sub_bar();
          .do_something();
          # this now does get_some_other_object.do_something()
}

sub some_sub_bar {
          $CALLER::_ = get_some_other_object();
}

That is kind of scary if call to another sub can hijack my method calls (I'm 
sure there are other ways to hijack the method calls - but having the 
invocant dynamically set offers too many dangers).  Maybe it isn't possible 
because $_ will be r only - but somehow I think $_ is rw and the invocant is 
r only.

To sum up...

If you are in a method then you get .method and it always works even if $_ is 
rebound to something else.

I think that the idea of $_ default to the invocant is necessary and good but 
the mistake comes in inferring that .method then must work on $_.

.method should work on the invocant period - it just happens to be a 
coincidence that $_ is the same as the invocant for most of the time.

Paul Seamons

I'll go back to lurking about now.

Reply via email to