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

I thought I understood the differences between || and or pretty well until I ran into this:
sub foo { my @bar = qw(one two three four); return @bar; }
Now if I use 'or' in calling foo() like this:
@foobar = foo() or warn "Yikes!\n";
All works as I expect, @foobar gets the list from foo()'s @bar, however if I use '||' like this:
@foobar = foo() || warn "Yikes!";
Then I get the scalar value of @bar in @foobar.

I'm very confused. how does using '||' instead of 'or' change what is returned by a sub?

TIA

Sweetblood

Replies are listed 'Best First'.
Re: '||' vs 'or' with subroutines
by diotalevi (Canon) on Nov 11, 2004 at 15:25 UTC

    Roy Johnson and hardburn are both wrong. Both || and or impose scalar context on their left operand. The difference is that or has a lower precedence than = so between the two forms, only the one using or was written correctly.

    @foobar = foo() || warn;

    @foobar = ( scalar( foo() ) || warn );

    @foobar = foo() or warn;

    scalar( @foobar = foo() ) || warn;
      Yes, that clears it up. An excellent example++.

      Thanks!

      Sweetblood

Re: '||' vs 'or' with subroutines
by demerphq (Chancellor) on Nov 11, 2004 at 15:30 UTC

    Operator precedence is the cause of this. || has much higher precedence than 'or' does. Consider the following:

    #!perl -l sub foo { print "Foo!"; return "foo"; } my $barbar=0 || foo(); print $barbar; print "---"; my $or =0 or foo(); print $or; __END__ Foo! foo --- Foo! 0

    What this shows is that $var = $x || $y; is handled as $var=($x || $y); and $var = $x or $y; is handled as ($var=$x) or $y; which is actually a logical operator used as flow control and as such is pretty well equivelent to unless ($var=$x) { $y }. Where this gets interesting is that its a lot nicer to write open my $fh,$mode,$file or die "$file:$!" than it is to write my $fh; unless (open $fh,$mode,$file) { die "$file:$!" }

    ---
    demerphq

Re: '||' vs 'or' with subroutines
by rev_1318 (Chaplain) on Nov 11, 2004 at 15:38 UTC
    how does using '||' instead of 'or' change what is returned by a sub?

    Precedence. 'or' has a higher precedence as '=', but '||' has a hihger precedence. Both operators force scalar context, but:

     @foo = @bar or warn "Oeps";

    can be read as

     (@foo = @bar ) or warn "Oeps";,

    assigning the contents of @bar to @foo and then evaluating the array @foo in scalar context, resulting in the length of @foo.

    On the other hand,

     @foo = @bar || warn "Oeps";

    will be evaluated as:

     @foo = (@bar || warn "Oeps";

    assigning the length of @bar (if it has any!) to the first element of @foo.

    HTH Paul

Re: '||' vs 'or' with subroutines
by Roy Johnson (Monsignor) on Nov 11, 2004 at 14:51 UTC
    Context. The || notation indicates that you want to logically-or the output of foo() (update the left operand of ||) with that of warn "Yikes!". You don't. Parentheses could make it work like you want:
    (@foobar = foo()) || warn "Yikes!";
    although I think it's more clear to use or for flow-control things like this.

    Update: Diotalevi's explanation is more clear, but mine is not "wrong". It is a matter of context being imposed on the output of foo() by the ||. or would put the (result of the) assignment in scalar context, which doesn't affect the assignment itself.


    Caution: Contents may have been coded under pressure.
Re: '||' vs 'or' with subroutines
by hardburn (Abbot) on Nov 11, 2004 at 14:51 UTC

    Because || forces scalar context.

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Re: '||' vs 'or' with subroutines
by PodMaster (Abbot) on Nov 12, 2004 at 11:08 UTC
    Don't forget to use B::Deparse to gain insight
    C:\>perl -MO=Deparse -e" @foobar = foo() || warn 'Yikes!'" @foobar = foo() || warn('Yikes!'); -e syntax OK C:\>perl -MO=Deparse -e" @foobar = foo() or warn 'Yikes!'" warn 'Yikes!' unless @foobar = foo(); -e syntax OK C:\>

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.