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

I have run into an odd corner of Perl behaviour I don't understand. I've simplified it down to the following snippet:

#! /usr/local/bin/perl -w use strict; sub one {1} sub two {2} sub three { one + two } print three, "\n"; # outputs 1 sub really_three { one() + two } print really_three, "\n"; # outputs 3

I don't understand why one + two returns 1 instead of 3. I have to force context with parens. This occurs on 5.005_03 and 5.8.6, the opposite ends of the spectrum of perl that interests me.

Is this a facet of some more useful behaviour that I haven't noticed before? Could someone please enlighten me as to what is going on?

- another intruder with the mooring in the heart of the Perl

Replies are listed 'Best First'.
Re: Puzzled by constant subs
by Anonymous Monk on Mar 09, 2005 at 11:22 UTC
    Because it's parsed as:
    sub three {one(+ two ())}
    You are missing one piece of the puzzle to make constant subs: the prototype:
    sub one () {1} sub two () {2} sub three {one + two}
Re: Puzzled by constant subs
by brian_d_foy (Abbot) on Mar 09, 2005 at 14:57 UTC

    The constant pragma will take care of this for you, too. Behind the scenes it creates subs with empty prototypes.

    use constant one => 1; use constant two => 2;
    --
    brian d foy <bdfoy@cpan.org>
      The constant pragma will take care of this for you

      This is true, and I use constants whenever I can, even though interpolating them into strings gets ugly quickly. I suppose that means I value constancy more than elegancy.

      The above snippet, however, is a simplification of the Real Word problem, and Anonymonk's suggestion about using prototypes was what I needed to get it straight.

      - another intruder with the mooring in the heart of the Perl

Re: Puzzled by constant subs
by theorbtwo (Prior) on Mar 12, 2005 at 11:26 UTC

    anonymonk gave the right answer, but a hint for debugging this sort of problem: perl -MO=Deparse,-p 437854.pl gives sub three as sub three { one(two()); }


    Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).