Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

or or

by ybiC (Prior)
on Jul 08, 2000 at 15:22 UTC ( #21641=perlquestion: print w/replies, xml ) Need Help??

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

In this post, btrott explains why the particular code should use or die"message$!"; instead of || die"message$!";.

I used || die in all my early scripts because that's what I learned from "Learning Perl" examples. Before I go back and change them all, in what code would || die be appropriate?

I know "Learning Perl" can't be wrong - mdillon said so here. grin

Replies are listed 'Best First'.
RE: or or
by reptile (Monk) on Jul 08, 2000 at 15:48 UTC

    Well, here's what the perlop manpage says:

      As more readable alternatives to && and || when used for control flow, Perl provides and and or operators (see below). The short-circuit behavior is identical. The precedence of ``and'' and ``or'' is much lower, however, so that you can safely use them after a list operator without the need for parentheses:
      unlink "alpha", "beta", "gamma" or gripe(), next LINE;
      With the C-style operators that would have been written like this:
      unlink("alpha", "beta", "gamma") || (gripe(), next LINE);

    So in other words, if you said this:

    unlink "alpha", "beta", "gamma" || gripe();

    the third argument to unlink would be "gamma" || gripe(); that is, always "gamma" and gripe() would never be evaluated.

    'or' is smarter than that. Look at C-style Logical Or and Logical or and Exclusive or on the perlop manpage. It talks a bit about why this happens.

    local $_ = "0A72656B636148206C72655020726568746F6E41207473754A"; while(s/..$//) { print chr(hex($&)) }

Re: or or
by ahunter (Monk) on Jul 08, 2000 at 15:53 UTC
    They differ in precedence, and are otherwise the same. This means that if you write:
    $a=$b || $c; $a=$b or $c;
    Perl evaluates this:
    $a=($b || $c); ($a=$b) or $c;
    This changes what gets assigned to $a, and can also change the context of a statement (from perlop):
    @info = stat($file) || die; # oops, scalar sense of stat! @info = stat($file) or die; # better, now @info gets its due
    This occurs because die is in scalar context, (so || is great for obfuscation!). || is also appropriate where you want to cause the rightmost value to get assigned. That is:
    $a=$b || $c
    Would assign $c to $a if $b was false, otherwise it would assign $b to $a. Whereas:
    $a=$b or $c
    Would not assign $c to $a when $b was false! In scalar context, using || for dieing is fine, but you'll run into trouble with things where context is important. or is almost always what you mean in these cases.

    If you still don't believe me, try this:

    $a=0 or 1; $b=0 || 1;
    $a will be 0, and $b will be 1.

    Andrew.

    

      >or is almost always what you mean in these cases.

      This is largely a matter of programming style, and the nature of the project, not something inherent to Perl. I find myself using || about ten times as often as or.

      Because most of my program data is non-zero, I find myself using a lot of things like:

      $param = $value || $default;

      OTOH, maybe I am using too many if/else blocks...

       

      Paris Sinclair    |    4a75737420416e6f74686572
      pariss@efn.org    |    205065726c204861636b6572
      I wear my Geek Code on my finger.
      
        I'm not sure what you mean here - you provide a classic example of where or is most certainly not appropriate (as if you use it, $param will never get the value of $default).

        That is,

        $param = $value or $default;
        Will result in $param always getting the value of $value, never $default. or has lower precedence than = (in fact it has the absolute lowest precedence of all the operators). Maybe it was just me not being clear, though. You should always use 'or' where what you really want to say is:
        ($param=$value) or die "darn"
        That is, you don't want the value of die to get assigned to $param (yeah, die doesn't return very often. But it forces scalar context, which is why the alternative is a Bad Thing). Using or, your example would have to be:
        $param=$value or $param=$default
        So it's not always a matter of style.

        Andrew.

Grouping Symbols?
by Kozz (Friar) on Jul 08, 2000 at 18:52 UTC
    Or that's what we call them in mathematics. If you use parentheses around the arguments of a function, I think this would remove any concern over "or" vs. "||".
    Like this:
    open(FH, "filename.txt") || die "$!"; # OR open(FH, "filename.txt") or die "$!";
    Functionality should be identical in the two cases above, no? Of course, this is only for calling of functions or something like that. It doesn't work the same with other above-mentioned examples such as
    $a = $b || $c;
    Which is an entirely different sort of thing.
      You are right, the functionality is identical in the cases you cite. But || comes with a *lot* of caveats when you use it in circumstances like this. The RHS of or will always be executed last (unless parentheses are used, or there is more than one or). This means if you want to say (psuedo-code):
      if (open fails) { die }
      or gives you a way of writing literally that. || means something a bit different, and can cause considerable confusion. It's a bad habit and a maintainance problem to use the wrong operator for the job. See perlop.

      Andrew.

      AFAIK, the examples you gave still pose a problem. What if you were to assign the return value of open() to a variable:

      $foo = open(FH, "filename.txt") || die $!; # not the same as $foo = open(FH, "filename.txt") or die $!;

      but they appear to be the same anyway ;) It's not the parentheses that's doing it, it's just the way it works. It's checking to see if the return of open() is true, and if not, tries to assign the return value of die to $foo, which never happens because it dies.

      So it works the same either way, but it's actually doing two different things.

      local $_ = "0A72656B636148206C72655020726568746F6E41207473754A"; while(s/..$//) { print chr(hex($&)) }

RE: or or (or generally better for die)
by ybiC (Prior) on Jul 08, 2000 at 16:34 UTC
    From reptile and ahunter's answers, it appears that using or instead of || for or die"message$!" would make an excellent habit, although not critical in every case.
    Update: the rest of this thread makes my brain hurt :-P
RE: or or (should be: or or ||)
by ybiC (Prior) on Jul 08, 2000 at 15:28 UTC
    Oops - forgot to escape the || in the post's title.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://21641]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (2)
As of 2022-05-27 06:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you prefer to work remotely?



    Results (94 votes). Check out past polls.

    Notices?