rir has asked for the wisdom of the Perl Monks concerning the following question:

Can the author of method have method determine which type of call was made?

That is: can it determine which form below was used?

method $obj $arg; method( $obj, $arg); $obj->method( $arg); "Classname"->method( $arg); method "Classname" $arg; method( "Classname", $arg);

Replies are listed 'Best First'.
Re: How called was &I?
by sauoq (Abbot) on Sep 16, 2002 at 00:08 UTC

    Well, method $obj $arg; would be an error. Update: Actually, that's not an error at all. rir++ for the catch. I updated the next paragraph to reflect this.

    You can't distinguish between

    method( $obj, $arg); $obj->method( $arg); method $obj $arg;
    because they are simply all instance methods. The last two listed there act just like the first one.

    Similarly, you can't distinguish between

    "Classname"->method( $arg); method "Classname" $arg; method( "Classname", $arg);
    because they are all class methods. The first two act just like the last one. Update: Poor assumptions made there. See rir's reply and mine to him for more insight. Otherwise, replace those examples with:
    Class->method($arg); method Class $arg; Class::method("Class", $arg);

    You can determine if the method was called as a class method or an instance method by checking the refness of the first argument but you can't determine the exact syntax.

    Update: Sorry for the mess. As I understand the question, you want to know if, for example, a method can know whether it was invoked via indirect object notation, a normal sub call, or with the arrow operator. My answer: a very long "no."
    -sauoq
    "My two cents aren't worth a dime.";
    
      method $obj $arg; is not an error.
      "Classname"->method( $arg); method "Classname" $arg; method( "Classname", $arg);
      The first two act just like the last one.

      Not so. Consider:

      #!/usr/bin/perl -w use strict; package Base; sub base { print "Base::base called\n"; } package Derived; use vars qw( @ISA); @ISA = ( "Base"); package main; Derived::base Derived "hello"; Derived::base( Derived,"hello"); # undefined Derived::base "Derived" "hello"; # syntax error
        method $obj $arg;is not an error.

        You are right. It isn't. I don't know what I was thinking.

        Before going on, I should clarify my point. Once a method is called, there is no way to determine the syntax used to invoke it. Your addition of a Derived class does nothing to show otherwise.

        That said, I made a couple of poor assumptions. One was that "Classname" in the original wasn't really meant to be a quoted string but a bareword. I also assumed that method would be the appropriate name for the method regardless of context. There really was no good reason to assume either and I should have requested clarification.

        # Actual original post # What I assumed the OP meant "Classname"->method( $arg); # Class->method($arg); method "Classname" $arg; # method Class $arg; method( "Classname", $arg); # Class::method(Class, $arg);

        Mistakes, assumptions, and mistaken assumptions aside, if I understand the original post, the answer is still "No."

        -sauoq
        "My two cents aren't worth a dime.";
        
Re: How called was &I?
by broquaint (Abbot) on Sep 16, 2002 at 12:48 UTC
    You can pretty much determine exactly how you were called
    use strict; use warnings; { package foo; use UNIVERSAL qw(isa); sub new { bless {}, shift } sub callme { my $invoker = (@_ == 2 ? shift : ''); my $package = [caller]->[0]; if(ref $invoker and isa($invoker, __PACKAGE__)) { if($package ne __PACKAGE__) { print 'called: $obj->method(@args)', $/; } else { print 'called: method($obj, @args)', $/; } } elsif($invoker eq __PACKAGE__) { if($package ne __PACKAGE__) { print 'called: foo->method(@args)', $/; } else { print 'called: method("foo", @args)', $/; } } elsif($invoker eq '') { if($package ne __PACKAGE__) { print 'called: foo::method(@args)', $/; } else { print 'called: method(@args)', $/; } } } } my $o = foo->new; my $arg = 'a string'; $o->callme($arg); foo->callme($arg); foo::callme($arg); callme $o $arg; # same as $o->callme($arg); # callme 'foo' $arg; # syntax error { package foo; callme($o, $arg); callme('foo', $arg); callme($arg); } __output__ called: $obj->method(@args) called: foo->method(@args) called: foo::method(@args) called: $obj->method(@args) called: method($obj, @args) called: method("foo", @args) called: method(@args)
    Of course this is assuming you know how many arguments you're expecting in your method, but it shouldn't be too hard to get around that.
    HTH

    _________
    broquaint

Re: How called was &I?
by Joost (Canon) on Sep 16, 2002 at 11:42 UTC
    The above discussion is very interesting, what follows is more or less the condensed (and hopefully clearer) conclusion:

    You can only distinguish between the first three and the last three calls:

    package Classname; sub method { print ref($_[0]) ? 'Object method' : 'Class method'; print "\n"; } package main; my $obj = bless {},Classname; my $arg = 1; # calls here method $obj $arg; Classname::method( $obj, $arg); # added Classname:: $obj->method( $arg); "Classname"->method( $arg); method Classname $arg; Classname::method( "Classname", $arg); # added Classname:: __END__ prints: Object method Object method Object method Class method Class method Class method
    Also note (as pointed out above) that the Classname::method calls (so, calls 2 and 6) do not support inheritance, as they are not actual method calls, but 'normal' subroutine calls pretending to be method calls.
    -- Joost downtime n. The period during which a system is error-free and immune from user input.
Re: How called was &I?
by BrowserUk (Patriarch) on Sep 16, 2002 at 11:51 UTC

    There's nothing I can (nor probably could) add to the sage wisdom already given, but I did get to wondering:

    Why did you want to make these distinctions in the firstplace?


    Well It's better than the Abottoire, but Yorkshire!
      Why did you want to make these distinctions in the firstplace?

      I don't! But the Calling Madness thread made me curious.

      Apparently, someone wanted to allow some various types of calls to be equivalent.
      So that his client authors could be completely naive.