Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

Returned value from subroutine is 1 when returning ""

by fidesachates (Monk)
on Jan 06, 2011 at 16:06 UTC ( #880846=perlquestion: print w/ replies, xml ) Need Help??
fidesachates has asked for the wisdom of the Perl Monks concerning the following question:

I noticed a behavior that I can not explain. I would appreciate anyone who could provide an explanation and expand on the subject. I have noticed that when a sub routine returns a "", the value that get stored is not always "". When you throw in a || onto the end of the calling statement, the return value is 1.
#!/usr/bin/perl -w use strict; my $o = mysub() || print STDERR "didn't work\n"; print $o; print "\n"; $o = mysub(); print $o; print "\n"; sub mysub { return ""; }
The first print will output a "1" while the second one will output the expect value of "". Can someone please explain why this occurs and any other symptoms like it? (E.g. If a different value gets returned depending on what the function after || is). Thanks.

Comment on Returned value from subroutine is 1 when returning ""
Download Code
Re: Returned value from subroutine is 1 when returning ""
by chromatic (Archbishop) on Jan 06, 2011 at 16:13 UTC

    The empty string evaluates to false in a boolean context, so the first value stored in $o is the return value of the print.

      Oh I understand now. I seem to have misunderstood the ||.

      I read the code as (my $o = mysub()) || print ...

      I see now that the grouping is my $o = (mysub() || print ...

      Thank you.

        When in doubt about what exactly the precedence will be, B::Deparse is your friend.

        $ perl -MO=Deparse,-b,-p -e 'my $o = mysub() || print STDERR "WHY U NO + WORK\n";' (my $o = (mysub() || print(STDERR "didnt work\n")));

        The cake is a lie.
        The cake is a lie.
        The cake is a lie.

Re: Returned value from subroutine is 1 when returning ""
by kennethk (Monsignor) on Jan 06, 2011 at 16:18 UTC
    You are having an issue with Operator Precedence and Associativity. The || binds more tightly than the assignment operator, so you are assigning the return value of the print to $o. What you have is equivalent to

    my $o = ( mysub() || print STDERR "didn't work\n" );

    You can get your exected result either with explicit parentheses

    (my $o = mysub() ) || print STDERR "didn't work\n";

    or by swapping to the lower precedence or

    my $o = mysub() or print STDERR "didn't work\n";

    See Logical or, Defined or, and Exclusive Or in perlop.

      Thanks for the links.
Re: Returned value from subroutine is 1 when returning ""
by mjscott2702 (Pilgrim) on Jan 06, 2011 at 16:21 UTC
    You should use "or" instead of "||" here, since it has lower precedence - in fact, I believe(?) this is the recommended practice.
      I recommend not using 'or', 'and' etc, but instead using brackets to make precedence explicit.
Re: Returned value from subroutine is 1 when returning ""
by sundialsvc4 (Monsignor) on Jan 06, 2011 at 16:57 UTC

    “Fair warning” here ...

    I advise that you should not write code which depends on the “truth value” of whatever-it-is that a subroutine or expression might yield.   If you expect that a sub will return, say, “an empty string,” or “an integer 1 or 0,” or “undef” or what-have-you, test specifically for that.

    And if you don't get anything you expect, (use Carp and) croak in a meaningful way.

    “Put debugging tests into your program and leave them in until you’re absolutely sure that every last bug is gone.   Then, and only then ... leave them in.”

    Sure, there are well-understood exceptions to that advice which we find everywhere in the language-of-use, such as the ... or die construct.   Such things are so well-known and widely accepted that they are probably just fine.   But the party that is always in the very best position to discover an error in a computer program is ... that computer program itself.   Within reason, the more that program(mer) takes the “I’m From Missouri... Show Me™” point of view, the more rugged and reliable his or her code turns out to be when it moves into production.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://880846]
Approved by Corion
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (6)
As of 2014-07-31 12:18 GMT
Find Nodes?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:

    Results (248 votes), past polls