Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Thoughts on using and, or, and not over && || !?

by Argel (Prior)
on Jul 11, 2016 at 22:13 UTC ( #1167582=perlquestion: print w/replies, xml ) Need Help??

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

Example: if( ! exists $dg_by_id{$group_id} and $group_id != 0) {}

Lately I've been writing scripts for an application with it's own lighter weight scripting language and a Perl API. The proprietrary language uses syntax such as

$model like /pattern/ $IPaddress in [ 192.168.0.0/24, 192.168.1.0/24 ] and $IPaddress not in + [ 192.168.0.1/32, 192.168.1.1/32]

, etc. Even in Perl scripts, we have to use some of their language to specify filters (like what to/not to run against) in the proprietary language format in a special comment block at the top. So, lately, even in Perl I've found myself writing 'and' instead of '&&" and ditto for 'or'. I'm not as fast to use 'not' instead of '!', but it's tempting. One benefit is for our non-programming users, they can make more sense of the Perl code.

My question is what's the risk/harm in using them like this? There's the low precedence that allows them to work, but I haven't been bitten by that yet (that I know of).

Elda Taluta; Sarks Sark; Ark Arks
My deviantART gallery

Replies are listed 'Best First'.
Re: Thoughts on using and, or, and not over && || !?
by Athanasius (Archbishop) on Jul 12, 2016 at 03:14 UTC

    Hello Argel,

    In addition to the potential predecence problems with or, it should be noted that Perl’s // (Logical Defined-Or) operator has no low-precedence equivalent, so if you get in the habit of using or in place of ||, you may more easily overlook situations in which // is a better fit:

    13:09 >perl -Mstrict -wE "my ($y, $z); my $x = (defined $y or defined +$z or 'default'); say $x;" default

    vs.

    13:09 >perl -Mstrict -wE "my ($y, $z); my $x = $y // $z // 'default'; +say $x;" default 13:09 >

    As a rule I use and and or for flow control only:

    open(my $fh, '<', $filename) or die "Cannot open file '$filename' for +reading: $!";

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Good post++. I would just add that the //= version of this operator is also available.
      my $xyz; $xyz //= 'default'; print $xyz; #default

      In addition to the potential predecence problems with or,

      Depends on context. While or is more likely to cause problems within an expression (aside from not being as visually distinctive), or is usually used for flow control because it's more likely to solve precedence problems in that situation. Compare

      open my $fh, '<', $qfn || die $!;
      with
      open my $fh, '<', $qfn or die $!;
Re: Thoughts on using and, or, and not over && || !?
by choroba (Archbishop) on Jul 11, 2016 at 22:20 UTC
    Just make sure you don't
    return $result or $default

    Fortunately, more recent perls would warn you:

    Possible precedence issue with control flow operator at ...

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      I'm using Perl 5.16.3, so I might get the warnings. Good example of where it could be a problem. Thanks!

      Elda Taluta; Sarks Sark; Ark Arks
      My deviantART gallery

Re: Thoughts on using and, or, and not over && || !? (purpose)
by tye (Sage) on Jul 12, 2016 at 18:24 UTC

    or was basically created for use in code like open ... or die .... That is why it was given extremely low precedence. It was not implemented as a "pretty" replacement for ||. So, or was meant to be used for flow control between statements while || continues to be meant for use in logical expressions.

    Using || for flow control between statements was often leading to bugs:

    open FOO, '<', $foo || die "Could not read $foo: $!\n";

    That is still an easy bug to introduce, so you should use or for such.

    So it should be no surprise that you can easily introduce bugs by using or for building logical expressions. In fact, I've seen quite a few bugs from quite a few different highly experienced Perl developers due to the use of or (or and) for building logical expressions.

    They didn't even realize that they had introduced the bugs. So, perhaps you are just way better than all of those highly experienced Perl developers I've worked with. Maybe, the people who say "I've never made such mistakes" are actually correct in their assessment despite the multiple examples of people who thought they had not made that mistake until I pointed it out to them.

    So I discourage people from using or for what || was designed for and vice-versa.

    No bug:

    if( $foo->is_ready() and $foo->needs_munging() ) { $status = $foo->munge(); } else { $status = $foo->status(); }

    Bug easily introduced:

    $status = $foo->is_ready() and $foo->needs_munging() ? $foo->munge() : $foo->status();

    No warning generated. Lots of different ways to make that same mistake.

    Hammers are ungainly and weirdly shaped. Screwdrivers are sleek and cylindrical. I pound nails in with screwdrivers because I think it makes the act of pounding in nails easier on the eyes. Some people think I'm silly for choosing my tools based on style considerations over how the tools were designed to be used. But I've never had problems with the nails I've pounded in, so what do they know?

    - tye        

      Can you give a second (distinct) example of where you've been bitten by the low-precedence?


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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". I knew I was on the right track :)
      In the absence of evidence, opinion is indistinguishable from prejudice.
        my $do_munge = $foo->is_ready() and $foo->needs_munging(); return $foo->is_ready() and $foo->needs_munging(); $count += $foo->willing() and $foo->able(); push @passes, $foo->tried() and $foo->success(); $separator = $args->{separator} or ','; skip_if( $not_mocked or $in_prod, sub { test_stuff() } ); LOG "Failure to launch.", because => $!, 'retry?' => $retries_left and + $not_fatal;

        - tye        

      But couldn't parenthesis be used with the low precedence operators in that example? Sometimes we have to use parenthesis with the high precedence operators (that's why "or" was created for flow control), so how is using them with the low precedence operators any different, beyond what came first/tradition?

      Elda Taluta; Sarks Sark; Ark Arks
      My deviantART gallery

        The problem with parentheses is you need to know where to put them. See e.g. this infamous Python question (I apologize to the God(s) of Programming for staining the Monastery):
        >>> False in [False, True] True >>> not (True) in [False, True] False >>> (not True) in [False, True] True

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Thoughts on using and, or, and not over && || !?
by eyepopslikeamosquito (Bishop) on Jul 12, 2016 at 20:22 UTC

    For flow of control, prefer the low precedence and and or operators. A common example of preferring or to || is:

    open(my $fh, '<', $file) or die "error opening '$file': $!";
    That is probably the principal use case as to why the low precedence operators were added to the language in the first place.

    Reserve && and || for logical expressions, not flow of control, for example:

    if ($x > 5 && $y < 10) ...

    This is discussed in detail in Perl Best Practices, Chapter 4, "Values and Expressions" in the "Don't mix high- and low-precedence booleans" item.

Re: Thoughts on using and, or, and not over && || !?
by Anonymous Monk on Jul 12, 2016 at 08:19 UTC
Re: Thoughts on using and, or, and not over && || !?
by Laurent_R (Canon) on Jul 12, 2016 at 12:42 UTC
    Both the high and the low precedence logical operators have their own pitfalls, so you have to be careful anyway.

    Having said that, I find that the low precedence logical operators express much more often what I want, probably in more than 90% of the cases, so that's what I am using most of the time. Also, since they are so low in the operator precedence list, I most of the time don't need to look up the documentation to find out if I am right.

    So, even though I tended to use the high-precedence operators when I picked up Perl, because of my background with C and C-derived languages, I quickly moved to and, or and not.

Re: Thoughts on using and, or, and not over && || !?
by Anonymous Monk on Jul 11, 2016 at 22:24 UTC

    I do it as often as I can. I think it makes code "more readable".

    (I also try to use as few parentheses as possible for the same reason.)

      "More readable" is always a judgement call. Redundant parenthesis are a big improvement to the reader that is spared from consulting the precedence tables.
      Bill
Re: Thoughts on using and, or, and not over && || !?
by Argel (Prior) on Jul 15, 2016 at 12:47 UTC
    Thanks for the advice everyone!!

    So, looking at the pro-high precedence arguments... What's the difference between using parenthesis for clarity and to address precedence issues with the high precedence operators vs. the low precedence ones? It seems like the answer to that is familiarity with the high precedence operators, the precedence for the high precedence operators, tradition, and of course older versions of Perl that do not have the low precedence operators.

    Put differently, if the low precedence operators had existed from the beginning and the high precedence ones were added recently the low/high arguments would be reversed.

    So, back to my situation.

    • We're using Perl 5.16.3 with the app and it either requires 5.14.x or 5.16.x.
    • My users are not programmers and most do not even write scripts. They do copy existing scripts to tweak them though.
    • The other language, which only uses "and", "or", and "not", ...
      • is normally used for simpler tasks (but can be used for moderately complicated stuff). Edit: In other words, we will be using both languages.
      • is the one our users are more likely to spend time learning (or learn by continued use over time).
      • has to be used in Perl scripts to specify the Script-Filter. For example:

    # BEGIN-SCRIPT-BLOCK # Script-Filter: # $vendor eq "Cisco" # and $sysdescr like /IOS/ # and $model like /2[89][05]/ # Script-Variables: # $tftp_server text "192.168.0.2" # $dest_name text # $source_name text # $MD5 text "Enter the MD5 hash for the source file here" # $reload_cmd text "reload at 00:00 reason New Firmware" # Script-Timeout: 300 # END-SCRIPT-BLOCK

    So, going back to what I wrote at the top. The main argument against the low precedence operators appears to boil down to "tradition" and backwards compatibility. The examples where it can trip someone up can be dealt with by using parenthesis, right? For example, for tye's example:

    $status = ( $foo->is_ready() and $foo->needs_munging() ) ? $foo->munge +() : $foo->status();

    Assuming parenthesis can be used to deal with the precedence issues and I am hard pressed to see why they cannot, then I think the other factors in my situation favor using the low precedence operators because it will be more "consistent" across the two scripting languages, which will make life easier for my mostly non-programmer user base. I am not going to claim it's ideal, but my job is to help them do their job.

    Elda Taluta; Sarks Sark; Ark Arks
    My deviantART gallery

      Hi Argel,

      In your situation (users are not programmers), I'd say it's easier to teach people to use parentheses everywhere than to teach them the operator precedence table, especially across multiple languages. If you use parens everywhere, it doesn't matter whether you use high- or low-precedence ops.

      Hope this helps,
      -- Hauke D

        I'd say it's easier to teach people to use parentheses everywhere than to teach them the operator precedence table
        I feel that is going too far. Since = is an operator, that advice requires you to use parens here:
        my $x = ( $y + 42 );
        Do you do that?

        Whether parens "clutter" or "clarify" is a matter of taste. I prefer the middle ground here to the extreme positions of "always use parens" or "memorize the precedence table and never use parens".

        That's an interesting idea. I don't think precedence is going to come up for them, at least not with the low precedence operators, so the advice may be "add parens if it's not working they way you thought it would". That way we get the readability. From my experience so far, use of parens to deal with precedence issues is going to very, very rare for our users. If they do run into issues, I may want them to talk to me about it anyway.

        Now I just need a 'like' operator in Perl for regex matching..... ;)

        Elda Taluta; Sarks Sark; Ark Arks
        My deviantART gallery

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (5)
As of 2021-11-27 12:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?