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

Oh wise monks of Perl, please explain the differences in the output of my humble subroutines.
for my $a (0, 1) { for my $b (0, 1) { print "c1 : $a, $b, ", c1($a, $b), "\n"; print "c2 : $a, $b, ", c2($a, $b), "\n"; } } sub c1 { my ($a, $b) = @_; $a and not $b } sub c2 { my ($a, $b) = @_; return $a and not $b }

output

c1 : 0, 0, 0 c2 : 0, 0, 0 c1 : 0, 1, 0 c2 : 0, 1, 0 c1 : 1, 0, 1 c2 : 1, 0, 1 c1 : 1, 1, c2 : 1, 1, 1

Replies are listed 'Best First'.
Re: To return and/or not?
by BrowserUk (Patriarch) on Oct 07, 2011 at 23:57 UTC

    With this

    return $a and not $b

    The return happens first, and regardless of the value of $a. The rest of the line is therefore never even considered.

    With this: $a and not $b the and is evaluated first, then the not $b if $a is false; then whatever is the result of that is returned by virtue of 'falling off the end' of the subroutine.

    You might use return $a && !$b instead.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: To return and/or not?
by roboticus (Chancellor) on Oct 08, 2011 at 00:06 UTC

    BrowserUk is spot on. Just by wrapping the expression in parenthesis, you'll get the same results from both functions:

    sub c2 { my ($a, $b) = @_; return ($a and not $b) }

    I went down a rabbit hole and was playing with Devel::Peek and trying to find clues as to why the returned values were different. Oh, well...

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: To return and/or not?
by moritz (Cardinal) on Oct 08, 2011 at 05:26 UTC
      I see. So basically the operators "and, or, xor" (and no others?) all have lower precedence than the return statement. Seems a strange decision.

        It seems to be the general sentiment that if a certain decision bites you, you consider it strange/weird/harmful/whatever, and forget all those idioms that are enabled by it.

        Yet all language design decisions are tradeoffs, and even generally good decisions bite you sometimes. Go figure.

        return is a normal listop, with normal listop precedence. The looser precedence of and/or/not is exactly the reason for having them. There wouldn't be any reason for them to exist if they had the same precedence as &&/||/!.

        The only thing perl could do better here is to warn about unreachable code in sub c2; but I think that has been tried before for if 0 { ... } code, and has been discarded at not helpful.

        Seems a strange decision.
        Not really. It make the famous
        open my $IN, '<', $filename or die "Cannot open $filename: $!\n";
        possible.

        So basically the operators...

        Yeah, perldoc perlop indeed says that not/and/or/xor have the lowest precedence

        left        terms and list operators (leftward)
        left        ->
        nonassoc    ++ --
        right       **
        right       ! ~ \ and unary + and -
        left        =~ !~
        left        * / % x
        left        + - .
        left        << >>
        nonassoc    named unary operators
        nonassoc    < > <= >= lt gt le ge
        nonassoc    == != <=> eq ne cmp ~~
        left        &
        left        | ^
        left        &&
        left        || //
        nonassoc    ..  ...
        right       ?:
        right       = += -= *= etc.
        left        , =>
        nonassoc    list operators (rightward)
        right       not
        left        and
        left        or xor

        Seems a strange decision.

        How many other programming languages do you know? That have the keywords not/and/or/xor as operators?