Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

two + 2 not equal 4!

by kp2a (Sexton)
on Jul 24, 2010 at 01:47 UTC ( #851101=perlquestion: print w/ replies, xml ) Need Help??
kp2a has asked for the wisdom of the Perl Monks concerning the following question:

Why should I not be surprised that the code below prints 2 and not 4?
File two.pl
#! /usr/bin/perl -w
use strict;
sub two {2}
printf "two + 2 = %d\n",two + 2;


john@scan test$ ./two.pl 
two + 2 = 2

testing:
printf "%d\n",two;  prints 2

Comment on two + 2 not equal 4!
Re: two + 2 not equal 4!
by morgon (Deacon) on Jul 24, 2010 at 02:05 UTC
    If you replace your last line with

    printf "two + 2 = %d\n",&two + 2;

    (note the ampersand) you get "two + 2 = 4". So it seems the parser treats your "two" as a bareword and converts it to 0 in numeric context (therefore the result).

    I wonder why this does not procuce a warning though...

      So it seems the parser treats your "two" as a bareword and converts it to 0 in numeric context
      No. A bareword would generate a compile error with strict. B::Deparse shows us what's going on.
Re: two + 2 not equal 4!
by toolic (Bishop) on Jul 24, 2010 at 02:09 UTC
    Tip #6 from the Basic debugging checklist: use B::Deparse to see if your code really is what you think it is:
    $ perl -MO=Deparse two.pl BEGIN { $^W = 1; } sub two { use strict 'refs'; 2; } use strict 'refs'; printf "two + 2 = %d\n", two(2);

    So, two + 2 is interpreted as two(2). Instead of evaluating your function, then adding 2, perl treats everything after your function call as a LIST of arguments when you omit the parentheses. From perlsub:

    2. NAME LIST; # Parentheses optional if predeclared/imported.

    While it is legal syntax to omit the parentheses on function calls, it is a good practice to use them, even if your function does not need arguments:

    printf "two + 2 = %d\n",two() + 2;

    As a side note, your code would render better if you replace your "pre" tags with "code" tags: Writeup Formatting Tips

Re: two + 2 not equal 4!
by sierpinski (Hermit) on Jul 24, 2010 at 02:13 UTC
    This works correctly too:
    #! /usr/bin/perl -w use strict; sub two {2} printf "two + 2 = %d\n",(two) + 2;
    Parens have precedence.
Re: two + 2 not equal 4!
by BrowserUk (Pope) on Jul 24, 2010 at 03:00 UTC

    A couple of ways, (that amount to the same thing), to make it right:

    use constant two => 2;; printf "two + 2 = %d\n", two + 2;; two + 2 = 4 sub two () { 2 };; printf "two + 2 = %d\n", two + 2;; two + 2 = 4

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: two + 2 not equal 4!
by nvivek (Vicar) on Jul 24, 2010 at 05:28 UTC

    If you want to know how it works clearly.You print the array @_ inside your subroutine.@_ is an array which contains the arguments passed to subroutine. If you call the subroutine without using &, then it will pass the data given after two subroutine will be passed.In your case, two + 2 2 will be passed as an argument. In the subroutine, you didn't handle anything with that argument.Then, 2 will be returned from that subroutine.That's why 2 gets printed. If you use &, then 2 from the subroutine will be returned and then it added with + 2 given.Then, it will print 4.

    use strict; use warnings; sub two { print @_; 2 } print "Two=%d\n", two + 2;

    If you want to have the array structure , use Dumper function which is in Data module.

Re: two + 2 not equal 4!
by suhailck (Friar) on Jul 24, 2010 at 06:15 UTC
    To make the print statement work as you wrote, change the sub as given below,

    perl -e 'sub two { $_[0] + 2 };print two + 2'

    output:
    4

    ~suhail
Re: two + 2 not equal 4!
by ikegami (Pope) on Jul 24, 2010 at 13:31 UTC

    So, two + 2 is interpreted as two(2).

    And that's because the following are all the same:

    two + 2 two +2 two(+2) two(2)

    Omitting parens around arguments can lead to weird problems. You've encountered one. You can disambiguate as follows:

    two() + 2 (two) + 2

    You could also add a prototype to two.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://851101]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2015-07-04 00:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (57 votes), past polls