Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

$obj->method v.s. $obj->method()

by perl5ever (Pilgrim)
on May 09, 2009 at 03:53 UTC ( [id://762998]=perlquestion: print w/replies, xml ) Need Help??

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

I know that &f and &f() are different in that the first call doesn't change @_ whereas the second call sets @_ to the empty list.

What about $obj->method v.s. $obj->method()? Are there any differences between the two calls?

Replies are listed 'Best First'.
Re: $obj->method v.s. $obj->method()
by moritz (Cardinal) on May 09, 2009 at 11:05 UTC
    There are tools in Perl that allow you to find things like that out by yourself.

    The first and easiest (but perhaps not always the most precise) is B::Deparse, which lets perl parse the program, and then reconstructs it from its internal representation. Let's try that:

    $ perl -MO=Deparse -ce '$a->method' $a->method; -e syntax OK $ perl -MO=Deparse -ce '$a->method()' $a->method; -e syntax OK

    So B::Deparse thinks the two are equivalent.

    If you don't trust that, you can get an output of the internal representation of Perl, which is called its op tree with B::Concise:

    $ perl -MO=Concise -ce '$a->method()' 7 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 6 <1> entersub[t2] vKS/TARG ->7 3 <0> pushmark s ->4 - <1> ex-rv2sv sKM/1 ->5 4 <#> gvsv[*a] s ->5 5 <$> method_named[PV "method"] ->6 -e syntax OK $ perl -MO=Concise -ce '$a->method' 7 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 6 <1> entersub[t2] vKS/TARG ->7 3 <0> pushmark s ->4 - <1> ex-rv2sv sKM/1 ->5 4 <#> gvsv[*a] s ->5 5 <$> method_named[PV "method"] ->6 -e syntax OK

    You don't have to understand its output (neither do I, although I see some sense in some of it), but you can simply compare the two outputs:

    $ perl -MO=Concise -ce '$a->method' > a -e syntax OK $ perl -MO=Concise -ce '$a->method()' > b -e syntax OK $ diff a b | wc -l 0

    (Don't compare them without a tool, it's too easy to miss a small difference in 2x 8 lines of weird symbols).

    So you see that both forms construct the same op tree.

    (You don't have to understand the rest of the post, if it confuses you just ignore it).

    That said, it's still no 100% proof, because the presence of the parenthesis might affect the parsing of the next term. To check that, you could try the same with

    $a->method / 1 # /; $a->method() / 1 # /;

    If the parser expects a term, the /.../ part will be parsed as a regexp, if it expects an operator it will parse the slash as the division operator, and the # takes care that the last slash isn't a syntax error. (Yes, I checked it; no, the parens don't make a difference).

      This is good info - thanks!
Re: $obj->method v.s. $obj->method()
by Burak (Chaplain) on May 09, 2009 at 04:02 UTC
    $obj->method will not work on some archaic perls (5.005 or 5.004 I guess) apart from that no.
       $obj->method will work on 5.004 at least, and I think on all 5.xxx versions.

      Unlike a 'non-method' function invocation, which can take arguments without using parentheses if the function is predeclared or pre-defined, the  $obj->method form cannot take arguments; if arguments are passed, a parenthesized list must be used, e.g.,  $obj->method('a', 'b'). (But see update below.)

      >perl -v This is perl, version 5.004_04 built for Intel Copyright 1987-1997, Larry Wall Win32 port Copyright 1996-1997 by Mortice Kern Systems Inc. MKS version 7.5 build 1183 Perl may be copied only under the terms of either the Artistic License or the GNU General Public License, which may be found in the Perl 5.0 source kit. >perl -wMstrict -le "package Foo; sub new { my $class = shift; return bless { @_ } => $class; } sub method { my $self = shift; return @{$self}{ @_ ? @_ : 'c' } } package main; my $foobj = Foo->new( qw(a 1 b 2 c 3) ); print $foobj->method; print $foobj->method( qw(b a) ); " 3 21 >perl -wMstrict -le "package Foo; sub new { my $class = shift; return bless { @_ } => $class; } sub method { my $self = shift; return @{$self}{ @_ ? @_ : 'c' } } package main; my $foobj = Foo->new( qw(a 1 b 2 c 3) ); print $foobj->method; print $foobj->method( qw(b a) ); print $foobj->method qw(b a); " syntax error at -e line 1, near "->method qw(b a)" Execution of -e aborted due to compilation errors. >perl -wMstrict -le "sub foo { print 'foo' . $_[0] } sub bar; foo 'zot'; bar 'zot'; sub bar { print 'bar' . $_[0] } " foozot barzot >perl -wMstrict -le "sub foo { print 'foo' . $_[0] } sub bar; foo 'zot'; bar 'zot'; baz 'zot'; sub bar { print 'bar' . $_[0] } sub baz { print 'baz' . $_[0] } " Bareword "baz" not allowed while "strict subs" in use at ... Unquoted string "baz" may clash with future reserved word at ... String found where operator expected at -e line 1, at end of line (Missing operator before ?) syntax error at -e line 1, near "baz 'zot'" Execution of -e aborted due to compilation errors.
      Update: It turns out that when run under ActiveState version 5.8.2,
      $foobj->method( qw(b a) ); $foobj->method qw(b a) ; $foobj->method( 'b', 'a' );
      all compile and all return the same values, but
      $foobj->method 'b', 'a' ;
      fails to compile.

        qw(b a) is (currently) equivalent to ('b', 'a') at a very low level. The parser only sees the latter.

        It also fools the x operator.

        >perl -le"$,=', '; print qw( a b c ) x 3" a, b, c, a, b, c, a, b, c >perl -le"$,=', '; print sub { qw( a b c ) }->() x 3" ccc

        Update: Even high level stuff like for.

        >perl -le"for my $x qw( a b c ) { print $x }" a b c
        $obj->method will work on 5.004 at least, and I think on all 5.xxx versions.

        As I recall, this feature was broken in a specific version of perl, caused by a wrong commit I think. But I couldn't locate something related to that now with a little Googling.

        $foobj->method qw(b a) ;
        Ah, that's interesting :) Recent perl (5.10 & 5.8.8) parses that as:
        C:\Users\burak>perl -MO=Deparse -e "$foobj->method qw(b a) ;" $foobj->method('b', 'a'); -e syntax OK [schultz]$ perl -MO=Deparse -e '$foobj->method qw(b a) ;' $foobj->method('b', 'a'); -e syntax OK [schultz]$
        it looks like qw() has some magic in it in recent versions
Re: $obj->method v.s. $obj->method()
by Bloodnok (Vicar) on May 10, 2009 at 00:48 UTC
    Your assertion, regarding the difference between $f; and &f();, doesn't ring quite true - consider
    sub frobnicate { &foo; &bar(); }
    The statement &foo; calls foo using a mirror image of @_ i.e. as passed to frobnicate - whereas, as you point out, &bar() calls bar with an empty argument list - but neither call i.e. to foo() or bar(), modifies @_ as passed to frobnicate.

    A user level that continues to overstate my experience :-))

      The statement &foo; calls foo using a mirror image of @_ /.../ neither call /.../ modifies @_ as passed to frobnicate

      By "mirror image" you mean the same, right? Just to be clear, the call &foo; may actually modify frobnicate's @_.

      See Re^2: Using & in function calls (&foo != foo(@_)) for an example.

      lodin

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://762998]
Approved by Burak
Front-paged by Burak
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (2)
As of 2024-04-20 10:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found