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

i find it odd that a no-regex-match would return anything but number 0, and always number 1 on match. i was expecting a 0 on non-match, but i got either undef or empty string. (my question is not why i get different values when used in list or scalar context.)

perl version is 5.6.1; below is the (tested) code to demonstrate the problem...

#!perl -w use strict; my $test; $test = 2; pr( 'no_zero' , $test , no_zero($test) ); # -> '1' pr( 'a_zero' , $test , a_zero($test) ); # -> '1' $test = 'pop'; pr( 'no_zero' , $test , no_zero($test) ); # -> 'undefined value' or '' pr( 'a_zero' , $test , a_zero($test) ); # -> '0' $test = undef; pr( 'no_zero' , $test , no_zero($test) ); # -> '' pr( 'a_zero' , $test , a_zero($test) ); # -> '0' sub no_zero { my $n = shift; my $re = qr/^ \d+ $/x; return #defined $n && $n =~ m/$re/ scalar( defined $n && $n =~ m/$re/ ) ; } sub a_zero { return no_zero( $_[0] ) || 0; } sub pr { my ($func , $val , $result) = @_; printf "%7s( '%s' ): '%s'\n" , ( $func , def($val) , def($result) ); sub def { my $v = shift; return ( (defined $v) ? $v : 'undefined value' ); } }

my overall goal was to use a sub like...

sub if_integer { my $i = shift; return defined $i && $i =~ m/^\d+$/; }

...i was surprised when instead of a false value got undefinded value when passed a defined and non-integer. i "solved" that problem by OR'ing w/ 0 which seems unnecessary...

return defined $i && $i =~ m/^\d+$/ || 0;

my question is why doesn't 0 is returned when m// fails, while 1 is returned on success?

Replies are listed 'Best First'.
Re: value returned on m// failure
by pg (Canon) on Dec 31, 2002 at 00:59 UTC
    1. Try this. You will find it is wrong when you said m// returns undef for non-integers, in fact the return value is empty string.
      $a = 123; print $a =~ m/^\d+$/, "\n"; $a = "abc"; $ret = ($a =~ m/^\d+$/); if (defined($ret)) { print "=$ret=\n";#print out == } else { print "undef";#not going this loop }
    2. Also try this, which tells you what is "true", what is "false" in Perl:
      sub true_false { if (shift()) { print "true\n"; } else { print "false\n"; } } true_false("a"); true_false(1); true_false(""); true_false(0); if (undef) { #I don't want to use true_false for this case, so it is g +uranteed that shift() does not play any magic print "true\n"; } else { print "false\n"; }
    3. Go perlop, and look under m//, there is a clear answer for the return value from m//, under different situations. Not just the context, but also the modifiers changes the meaning of the return value from m//

      i am quite aware of what values are ture and what are false. explicitly, undef and empty string are false values. and the perlop says...

             m/PATTERN/cgimosx
             /PATTERN/cgimosx
                     Searches a string for a pattern match, and in
                     scalar context returns true if it succeeds, false
                     if it fails. ...
      

      ...it doesn't say anything about what the actual values are.

      i was asking why is that to express success number 1 is returned, yet a non-number is returned on failure. is it an implementation detail/decision such that empty string is easier/faster to return than the number 0?

        It doesn't return 1 for success. It returns the number of matches (or substitutions for s/// or tr///). If you're not using the g option, it stops on the first match and returns 1. I'm not really up on perl internals but I would guess undef is represented as a null pointer whereas a zero would require creation of an SV.

        --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';

        m// returns true or false in scalar context. Perl defines:

        NAMEValue as StringValue as NumberPerl Internal Variable
        true"1"1PL_sv_yes
        false""0PL_sv_no

        For evidence, see the source code module perl.c where PL_sv_yes and PL_sv_no are initialized. Also see the pp_match code in pp_hot.c where RETPUSHYES and RETPUSHNO are used to return a boolean value when invoked in scalar context without /g.

        Let me show you a piece of code first:
        $_ = 123; print 1 + m/^\d+$/, "\n"; # get 2 print "1" . m/^\d+$/, "\n"; #get 11
        What does this piece of code tell us? It clearly tells us that, it is meaningless to ask the question whether m// returned a string or a number. The answer is only meaningful, when you use the returned value for a PURPOSE, either as a number, or as a string.

        This is the flexibility we get from Perl.

        Something not related, yet related:

        Before you look at it, the Schrodinger's cat is both dead and alive. Dead or alive only becomes determined after you looked at the cat.
Re: value returned on m// failure
by BrowserUk (Patriarch) on Dec 31, 2002 at 01:03 UTC

    The "undefined value" does test false?

    sub if_integer{ return defined $_[0] && $_[0] =~ m/^\d+$/; } if_integer($_) and print $_, ' is an integer', $/ for -1, 0, 1, 2, 2.2, 1E0, '1E2', 'A', '123', '123 fred' 0 is an integer 1 is an integer 2 is an integer 1 is an integer 123 is an integer

    So the logic of the test works fine.

    Of course your regex is a little primitive as it excludes all negative integers, as well as those represent in exponential form, '1E0' for example.


    Examine what is said, not who speaks.

    The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

      yes undef is false but causes problem if used as is when some non undef value is expected. thus the addition of '|| 0' in the function.