Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re: return value of "if" (documentation?)

by davido (Archbishop)
on Jan 07, 2014 at 23:18 UTC ( #1069711=note: print w/ replies, xml ) Need Help??


in reply to return value of "if" (documentation?)

Re-read the documentation in perlsub (Link updated; thanks ikegami.) and you will see two big red flags. First:

If no return is found and if the last statement is an expression, its value is returned.

In this construct: my $val = do { if(0){1} };, the last statement evaluated is the conditional, which is numeric zero, so $val gets 0. Had the conditional been true, the last expression evaluated would be the last one in the if statement's block (1, in this case). So unless you explicitly specify an "else" condition, your last expression will be the conditional from the if() statement, if that condition proves false.

The next red flag:

If the last statement is a loop control structure like a foreach or a while , the returned value is unspecified.

So now if your conditional looks like this: my $val = do { if( 1 ) { for( 0 ) { $_ } } };, all bets are off; the behavior is unspecified: You might get a '0' (the last expression), or not... or your keyboard may burst into flames, though Perl isn't prone to doing that under most circumstances. ;)

do{}; blocks can be thought of as immediate-execution subroutines, with implicit(-only) return values.

This tricky behavior is the reason for the recommended ban on "Implicit Returns" in Perl Best Practices (page 197).


Dave


Comment on Re: return value of "if" (documentation?)
Select or Download Code
Re^2: return value of "if" (documentation?)
by MidLifeXis (Prior) on Jan 08, 2014 at 14:26 UTC

    or your keyboard may burst into flames, though Perl isn't prone to doing that under most circumstances.

    This guy might disagree ;-)

    --MidLifeXis

Re^2: return value of "if" (documentation?)
by ikegami (Pope) on Jan 08, 2014 at 15:10 UTC

    I can't find either quotes in the linked document? You're quoting perlsub, not perlsyn.

    An if statement is neither an expression nor a loop control structure, so neither quoted passages apply (wherever you quoted them from). perlsyn simply does not cover the situation. You should consider it unspecified as well.

      You're right; I intended to link to perlsub. I still think that it's applicable, though I would be in full agreement that the documentation ought to be more explicit about it, unless specifying the behavior more explicitly locks future p5p development into a behavior that they would prefer to change.

      Update:

      I've submitted the following perlbug:
      ----------------------------------------------------------------- [Please describe your issue here] perlsub says this about implicit returns: If no return is found and if the last statement is an expression, its value is returned. If the last statement is a loop control structure like a foreach or a while , the returned value is unspecified. Now consider the following code: $x = 1; sub foo { if( $x ) { 0 } } print foo(), "\n"; The output will be 0, presumably because the last statement is the expression, numeric '0'. How about this: $x = 0; sub foo { if( $x ) { 1 } } print foo(), "\n"; The output will be 0, presumably because the last expression to be evaluated is '$x', which has a value of 0. But the last statement to execute is literally "if()". If we run this past B::Concise we find that the construct is converted into something similar to sub { $x and 1 }, so it is intuitive that the return value will be $x if false, or 1 if $x is true. Although this behavior is possibly a little confusing to someone who doesn't read between the lines in perlsub, it seems reasonably stable (it's been with us forever), and unlikely to change in the future. Therefore, perlsub should state the following: If no L<return> is found and if the last statement is an expression, its value is returned. If the last statement is an C<if( CONDITION ) { BLOCK }> construct, the value of the return value will come from C<BLOCK> if C<CONDITION> is true, or from C<CONDITION> if C<CONDITION> is false. Relying on this behavior is detrimental to code legibility. If the last statement is a loop control structure like a C<foreach> or a C<while>, the returned value is unspecified. [Please do not change anything below this line] ----------------------------------------------------------------- ---

      If it gains the consideration of p5p I anticipate they will want to rehash the wording a bit before proceeding, or possibly simply make the if(){} construct explicitly unspecified, as has been done with loop constructs.


      Dave

Re^2: return value of "if" (documentation?)
by Anonymous Monk on Jan 15, 2014 at 23:36 UTC
    ... the last statement evaluated is the conditional...
    do{}; blocks can be thought of as immediate-execution subroutines, with implicit(-only) return values.

    These two things in particular cleared things up for me very well, thank you very much! The second one also clears up why an empty do{} returns undef or the empty list depending on context. Although now I can't help but wonder where that is documented, if at all...?

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2014-12-28 22:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (183 votes), past polls