Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

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

by Argel (Prior)
on Jul 15, 2016 at 12:47 UTC ( [id://1167830]=note: print w/replies, xml ) Need Help??


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

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

Replies are listed 'Best First'.
Re^2: Thoughts on using and, or, and not over && || !?
by haukex (Archbishop) on Jul 15, 2016 at 13:00 UTC

    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".

        I feel that is going too far. Since = is an operator, that advice requires you to use parens here:

        my $x = ( $y + 42 );

        You meant to type:

        ( my $x ) = ( $y + 42 );

        You could theoretically teach people to use parentheses everywhere, but much of the resulting code would be completely unreadable (worse than LISP). "Never use parens" is, of course, not really an option. It isn't just that some constructs require parens for reasons other than clarifying precedence: ( 1 ) x 10. So, $a*$b + $c gets parsed in agreement with the spacing I used. If I want to instead calculate $a * $b+$c, then I should just add parens: $a*( $b + $c ); those ones aren't a matter of taste. There are more convoluted ways to avoid such parens, but always going that route is beyond just a "style choice".

        Whether parens "clutter" or "clarify" is a matter of taste

        Well, I can concur that "one set of parens vs. zero parens" in many cases boils down to a matter of taste. But more than 2 levels of parens does not "clarify", for most people. As I said recently, I have had (only a couple of) people tell me that they have no problems matching up deeply nested parentheses. But I actually tested them by showing them code with and without parentheses and they were unable to quickly find the bug in the code with parentheses 3 or 4 levels deep. There certainly could be some people who can really do that, but my experience is that such people are so rare that I've not yet met one. So I don't find it wise to use "extra" parentheses. And I often find it wise to go the more convoluted routes when code ends up actually needing 3 or more levels of (required) parentheses.

        Nor do I advocate "memorize the precedence table". I find memorizing is usually a poor choice in general. A much easier approach is "understand the precedence table". It is quite easy.

        So, there are a lot of utterly mundane coding situations for which the precedence table was well designed. In such mundane situations, adding parens because you haven't bothered with the small effort to learn how precedence "just works" there can make the code harder to parse for the majority of people.

        For the non-mundane coding situations, sure, add clarifying parens. But almost always avoid nesting them deeply.

        If you are masking bits, then sure, use maximal parens and if you end up with 3 or even 4 levels of parens, then just make sure your expression is short enough and use spacing to aid visual parsing. The precedence of bit operators is, well, just wrong. So, even if one set of parens is not required when masking bits, include them anyway because understanding that part of the precedence table is more of a lesson in history than in anything logical and we shouldn't require people to understand obscure bits of history (or to go read the table again) in order to understand your code.

        'and', 'or', and 'not' are for flow control between "statements" and so have the lowest precedence. You are also allowed to use comma to separate "statements". Comma binds tighter than 'or' (etc.) otherwise "open FOO, ... or die ..." would be parsed wrong.

        Assignment is one of the most common types of statements and you might want to assign a boolean value so assignment operators bind the next most loosely. (So you need to use parens if you want to do an assignment that involves commas.)

        ?: takes a logical expression as an argument so it goes next. Then we have the logical operators (mostly '||' and '&&') that are often used to combine comparisons. So comparison operators come after those. (So you should use parens if you want to use an assignment as part of a comparison or logical expression.)

        Then we have mundane expression operators.

        Add to this the preference of mathematicians that '*' binds tighter than '+' and that 'and'-like operations are like '*' and 'or'-like operations are like '+', and you've got almost all of the sane details of the whole precedence table down. (Mathematicians also prefer unary operators to bind tighter than binary ones.)

        Anything that isn't clear from that is at least a candidate for adding parens, even when they aren't needed. So you write "Found " . ($last+1) . " items". Though, I'd actually instead write that as join ' ', "Found", $last+1, "items" (which is a reason why die takes a list not just a single string and why your 'print'-like routines should as well).

        - tye        

        Hi eyepopslikeamosquito,

        Ok, "everywhere" may be a bit of an exaggeration :-) But I do still think that parens are easier to learn and remember than the precedence table, especially across multiple languages. That doesn't exclude learning precedence, just that learning proper use of parens could be the first step, followed by learning when they don't need to be applied. And I was speaking in the context of Argel's situation, "users are not programmers and most do not even write scripts", where my priority would be on getting the users writing working code, style comes after.

        Regards,
        -- Hauke D

      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

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

        You could create a module with a like function in it, but it would act like a "prefix" operator:

        like $line, "pattern"

        As best I can tell, Perl's keyword API can only create prefix operators.

        However, you could use Filter::Simple to "create" your like operator. (Though most Perl experts consider using source filtering to be a very BAD thing to do.)

        package Like; use Filter::Simple; FILTER_ONLY code_no_comments => sub { s/\s+like\s+/ =~ /; }; 1;

        Caveat:

        My example filter is probably too simple and will probably replace occurrences of like it should not.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (4)
As of 2024-04-20 00:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found