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

Monks, I'm following the example for the chown perldoc. I wonder why I get different results using operators || and or. Should I start using or consistently?
$ perldoc -f chown ($login,$pass,$uid,$gid) = getpwnam($user) or die "$user not in passwd file";
$ perl --version This is perl, v5.8.5 built for i386-linux-thread-multi $ uname -a Linux hopalong 2.6.9-42.0.10.EL #1 Tue Feb 27 09:24:42 EST 2007 i686 i +686 i386 GNU/Linux $ perl -wle 'use strict; my (undef,undef,$uid,$gid) = getpwnam(q[roo]) + || die "oh no"; print $uid;' Use of uninitialized value in print at -e line 1. $ perl -wle 'use strict; my (undef,undef,$uid,$gid) = getpwnam(q[roo]) + or die "oh no"; print $uid;' 500
Thanks.

Andreas

Replies are listed 'Best First'.
Re: || vs or
by mickeyn (Priest) on May 16, 2007 at 06:51 UTC
    the two operators have different precedence ...

    'or' has lower precedence than ||, and it usually becomes an issue when comma is involved (lower precedence than ||, higher than 'or')

    please read perldoc perlop.

    Mickey

Re: || vs or
by FunkyMonk (Bishop) on May 16, 2007 at 08:24 UTC
    Should I start using or consistently?
    For what it's worth, I always use or for statement modifiers and || as part of boolean expressions.

    if ( $1 eq 'A' || $1 eq 'B' ) { ... } open my $fh, "<", $filename or die "can't open $filename: $!";
      $ perl -mO=Deparse -e 'if ( $1 eq 'A' || $1 eq 'B' ) { }' if ($1 eq 'A' or $1 eq 'B') { (); }
      :) I'm a bit surprized to see that things seem to be OK despite the lack of apostroph escaping - but you see that, at least in this case, 'or' is quite OK.
      Anyway, I try to follow the advice in Damian Conway's "Perl Best Practices" and prefer to write that as
      if( ($1 eq 'A') or ($1 eq 'B') ) { ...}
Re: || vs or
by Krambambuli (Curate) on May 16, 2007 at 08:30 UTC
    The following might help in getting light on the issue:
    #!/usr/bin/perl use strict; #use warnings; my ( undef, undef, $uid, $gid ) = getpwnam( 'roo' ) || warn "Oh no - || and not existent user roo\n"; print "1. UID: $uid, GID: $gid\n\n"; ( undef, undef, $uid, $gid ) = getpwnam( 'root' ) || warn "Oh no - || and existent user root\n"; print "2. UID: $uid, GID: $gid\n\n"; ( undef, undef, $uid, $gid ) = getpwnam( 'roo' ) or warn "Oh no - OR and not existent user roo\n"; print "3. UID: $uid, GID: $gid\n\n"; ( undef, undef, $uid, $gid ) = getpwnam( 'root' ) or warn "Oh no - OR and existent user root\n"; print "4. UID: $uid, GID: $gid\n\n";
    If you put the code in test.pl for example, try to run then
    perl -MO=Deparse ./test.pl
    (have a look on B::Deparse). It shows you how Perl understands the code you've written in each case.

    Update. It isn't really something guaranteed to work, but I use to imagine '( || )' as opposed to ')or(' to keep in mind the much lower precedence of 'or'. And whenever I'm in doubt, I prefer to place the parens explicitely. It's not something to be ashame of ;)
Re: || vs or
by cdarke (Prior) on May 16, 2007 at 07:39 UTC
    As mickeyn said, it is a precedence problem. With the hight precedence operator || you need an extra set of parentheses:
    (my (undef,undef,$uid,$gid) = getpwnam(q[user1])) || die "oh no";
    You asked "Should I start using or consistently?" IMO it is a good idea to do everything consistently, or to have a good reason for not doing so.
Re: || vs or
by Tanktalus (Canon) on May 16, 2007 at 17:22 UTC
Re: || vs or
by davido (Cardinal) on May 16, 2007 at 20:38 UTC

    Should I start using 'or' consistently?

    Consistency is always a good thing. But if you mean "exclusively", the answer should be no. 'or' and || have subtly different meanings (as others have pointed out; it's a precedence thing), and thus, have different uses. Try to be consistent on when and how you use them, but don't subject your code to contortions just to enforce exclusivity.


    Dave

      To the first approximation, use || when you want to find the first true value in a list of values, and use or when you want to do logic on the results of expressions. The or precedence level was added specifically in order to do logic on the results of list operators without requiring them to be turned into function calls with parens. Hence or is generally used as control flow between "almost statements", and typically reads better for logic within a boolean context too. The || operator is mostly relegated to picking fallback or default values, and in fact much of that usage will end up using // in the future instead.