Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re: variable set to 0 ? 0 : 1

by Aristotle (Chancellor)
on Sep 06, 2002 at 06:05 UTC ( [id://195585]=note: print w/replies, xml ) Need Help??


in reply to variable set to 0 ? 0 : 1

The explanation has already been given exhaustively, but I want to expand a bit on semantics here.

Returning zero in Perl is usually a bad meme. It is ok if you actually meant to return a numeric zero, but if you mean to return "false", the Perlish way is to return an empty list <update> in list context and undef otherwise. </update> This is because by returning 0 you return a single-element list, which evaluates to true in list context. The code would then look like this:

return $status == 0 ? (wantarray ? () : undef) : 1;
or maybe better
return 1 if $status == 0;
return; # a return by itself implicitly returns an empty list
Another pitfall may or may not be the == 0. Is it meant to test falseness? If so, it is not precise. Perl understands the notion of an undefined value <update> and also considers a defined but empty string as well as a literal string "0" to be false </update>, which are not the same as zero, so this test is broken if it means to check falseness. In all likelihood, the programmer there should have written
return 1 if $status; return;

Updated: thanks ++Flexx. Moved one code example, added a few small but important bits.

Makeshifts last the longest.

Replies are listed 'Best First'.
Re: Re: variable set to 0 ? 0 : 1
by hossman (Prior) on Sep 06, 2002 at 07:51 UTC
    Returning zero in Perl is usually a bad meme. It is ok if you actually meant to return a numeric zero, but if you mean to return "false", the Perlish way is to return an empty list. This is because by returning 0 you return a single-element list, which evaluates to true in list context. The code would then look like this:

    The opposite could be argued just as easily: if you return an empty list to mean "false", the false-ish-ness could be lost (or other problems could arise) if your return value is "slurped" into another list context.

    Consider...

    #!/usr/local/bin/perl -wl use strict; sub a_func_that_returns_false { return 0; } sub your_func_that_returns_false { return (); } sub func_that_expects_string_boolean_and_num { my $str = shift; my $bool = shift; my $num = shift; print "CALLED FUNC: ", $str; print " bool was ", ($bool ? "true" : "false"); print " num was ", (20 < $num ? "bigger" : "smaller"), " then tw +enty"; } &func_that_expects_string_boolean_and_num ("the zero way", &a_func_that_returns_false(), 42); &func_that_expects_string_boolean_and_num ("the empty list way", &your_func_that_returns_false(), 42); __DATA__ laptop:~> monk.pl CALLED FUNC: the zero way bool was false num was bigger then twenty CALLED FUNC: the empty list way bool was true Use of uninitialized value in numeric lt (<) at monk.pl line 12. num was smaller then twenty

    Bottom line: there's no substite for using wantarray to check your calling context, and acting appropriately (except perhaps extensively documenting that your method may not work the way people think and making it their responsibility to force the calling context)

    Update: good point blakem

      there's no substite for using wantarray to check your calling context
      Interesting example, though I fail to see how wantarray will help in this case:
      sub use_wantarray { return wantarray ? () : 0 }
      Wont work properly in your example either.... Note that the above sub is equivalent* to the recommended way to return false, i.e. simply return:
      sub recommended_way { return; }
      * except when used in void context, but that isn't relevant here.

      -Blake

Re(2): variable set to 0 ? 0 : 1
by Arien (Pilgrim) on Sep 06, 2002 at 07:42 UTC
    ... if you mean to return "false", the Perlish way is to return an empty list. This is because by returning 0 you return a single-element list, which evaluates to true in list context.

    I feel the risk of that happening is mildly exaggerated. :-)

    If you directly evaluate the return value of the sub for truth you supply the sub a Boolean context, and there will be no problem.

    To run into problems, you'd have to call the sub in a list context, save the list of 1 return value and then evaluate that in scalar context. But then the problem would be evaluating a list in scalar context when you didn't mean to.

    — Arien

      The risk of that happening may be small, but it's a question of principle and good habit. Specifically, a question of principle of least surprise. If you simply return when you mean to return "false", your code will do the right thing in most cases without requiring hoop jumps on the part of the caller. There are obviously reasons to deviate from the standard idiom in specific cases, but you should be aware what the standard idiom is and why it is that; so that you know when and when not to apply it.

      Makeshifts last the longest.

Re: Re: variable set to 0 ? 0 : 1
by hossman (Prior) on Sep 06, 2002 at 08:01 UTC
    Another pitfall may or may not be the == 0. Is it meant to test falseness? If so, it is not precise. Perl understands the notion of an undefined value, which is not the same as zero, so this test is broken if it means to check falseness.

    Well, accutally.... it's true that undefined is not the "same" as zero, but they are numericly equal. As you can see, it generates a warning, but it does evaluate to true...

    laptop:~> perl -wle 'print "TrUe" if undef == 0' Use of uninitialized value in numeric eq (==) at -e line 1. TrUe

    A better example as to why you wouldn't want to use "$status == 0" as a test for truth is non numeric strings. the string "foo" is true, but it is numericly equal to 0...

    laptop:~> perl -le 'print "TrUe" if "foo" == 0' TrUe laptop:~> perl -le 'print "TrUe" if "foo"' TrUe
Re^2: variable set to 0 ? 0 : 1 (return by itself returns undef in scalar context)
by Flexx (Pilgrim) on Sep 06, 2002 at 12:51 UTC
    return 1 if $status == 0; return; # a return by itself implicitly returns an empty list

    It's true that return by itself returns an empty list in list context. But it returns undef in scalar context -- not   scalar( () )! ;)

    Updated: Simply added a quote of what I was refering to, since the thread grew quite long. Improved punctuation to boost readability. Removed unneccesary extra link to return.

      Excellent catch; I updated my node.

      Makeshifts last the longest.

Re^2: variable set to 0 ? 0 : 1
by diotalevi (Canon) on Jan 23, 2007 at 07:28 UTC

    You'll love this. If you return -0.0 then it's false and equal to zero unless you compared it to a string at some time and then it becomes true and equal to zero.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://195585]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (10)
As of 2024-03-28 10:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found