Hi list,

I just ran across some unexpected results in passing arguments to
user-defined subroutines.  Could someone who has been around Perl a while
longer check this and make sure I'm seeing this right?

I've got some code that implements a constant as a subroutine call (to keep
the constant from being modified).  When I use that subroutine in an
arithmetic expression, it is consuming everything to the right of it as its
argument list.  It looks like one simply needs to be careful in the
following case:

- user-defined subroutine, where
- subroutine does not validate incoming arguments
- subroutine has no prototype 
- ... -or- prototype not defined at point of actual subroutine call (ie is
called relative to its own namespace and not by name imported into caller's
namespace)
- is called as plain old subroutine and not as method

I have to say this is rocking my world -- because of the potential for such
code to die silently in a number of situations not hard to imagine -- but I
guess that someone who's been around Perl for a while would not be
surprised by this. 

Am I reading the situation correctly?  Thanks!

Example subroutine call that fails:
----------------------------------
print MyProject::CoreConstants::EarliestValidTimestampAsNumber+1, "\n"; #
fails -- the result does not have +1 added to it


The module:
----------
package MyProject::CoreConstants;

use strict;
use warnings;
use Time::Local;

[ .. comments deleted .. ]
sub EarliestValidTimestampAsNumber { 

    # pass in 2000-01-01 00:00:00 as timegm expects it 
    # (i.e. as would be returned by gmtime)
    # so that we get correct number of seconds offset from start of epoch
    
    return timegm(0,  # second zero
                  0,  # minute zero
                  0,  # hour zero, on
                  1,  # the first day of
                  0,  # January
                  100 # 2000
                  ); 
    }
1;


Test code:
---------
[ .. lots of preamble deleted .. ]
if( $testcase eq "62.3" ){
    print "as sub: without grouping: ",
MyProject::CoreConstants::EarliestValidTimestampAsNumber+0, "\n"; # fails
    print "as sub: without grouping: ",
MyProject::CoreConstants::EarliestValidTimestampAsNumber+1, "\n"; # fails
    print "as sub: without grouping: ",
MyProject::CoreConstants::EarliestValidTimestampAsNumber+2, "\n"; # fails
    print "as sub: with arg parens: ",
MyProject::CoreConstants::EarliestValidTimestampAsNumber()+0, "\n"; # the
rest work as expected
    print "as sub: with arg parens: ",
MyProject::CoreConstants::EarliestValidTimestampAsNumber()+1, "\n";
    print "as sub: with arg parens: ",
MyProject::CoreConstants::EarliestValidTimestampAsNumber()+2, "\n";
    print "as sub: with grouping: ",
(MyProject::CoreConstants::EarliestValidTimestampAsNumber)+0, "\n";
    print "as sub: with grouping: ",
(MyProject::CoreConstants::EarliestValidTimestampAsNumber)+1, "\n";
    print "as sub: with grouping: ",
(MyProject::CoreConstants::EarliestValidTimestampAsNumber)+2, "\n";
    print "as method: without grouping: ",
MyProject::CoreConstants->EarliestValidTimestampAsNumber+0, "\n";
    print "as method: without grouping: ",
MyProject::CoreConstants->EarliestValidTimestampAsNumber+1, "\n";
    print "as method: without grouping: ",
MyProject::CoreConstants->EarliestValidTimestampAsNumber+2, "\n";
    print "as method: with arg parens: ",
MyProject::CoreConstants->EarliestValidTimestampAsNumber()+0, "\n";
    print "as method: with arg parens: ",
MyProject::CoreConstants->EarliestValidTimestampAsNumber()+1, "\n";
    print "as method: with arg parens: ",
MyProject::CoreConstants->EarliestValidTimestampAsNumber()+2, "\n";
    print "as method: with grouping: ",
(MyProject::CoreConstants->EarliestValidTimestampAsNumber)+0, "\n";
    print "as method: with grouping: ",
(MyProject::CoreConstants->EarliestValidTimestampAsNumber)+1, "\n";
    print "as method: with grouping: ",
(MyProject::CoreConstants->EarliestValidTimestampAsNumber)+2, "\n";
    print "End of test.\n";
    }
        
Test output:
-----------
# you can see that the first three calls erroneously consume the '+1' or
'+2' as well as the "\n"
as sub: without grouping: 946684800as sub: without grouping: 946684800as
sub: without grouping: 946684800as sub: with arg parens: 946684800
as sub: with arg parens: 946684801
as sub: with arg parens: 946684802
as sub: with grouping: 946684800
as sub: with grouping: 946684801
as sub: with grouping: 946684802
as method: without grouping: 946684800
as method: without grouping: 946684801
as method: without grouping: 946684802
as method: with arg parens: 946684800
as method: with arg parens: 946684801
as method: with arg parens: 946684802
as method: with grouping: 946684800
as method: with grouping: 946684801
as method: with grouping: 946684802
End of test.




-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to