Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

Re^5: Thoughts on using and, or, and not over && || !? (alternatives)

by tye (Sage)
on Jul 16, 2016 at 20:42 UTC ( #1167890=note: print w/replies, xml ) Need Help??

in reply to Re^4: Thoughts on using and, or, and not over && || !? (a few cases)
in thread Thoughts on using and, or, and not over && || !?

strength of feeling you have on the subject

It may come across that way more strongly than I feel it because, as usual, I try to consider potential readers and try to anticipate counter arguments or how they might misinterpret what I've written and that often leads to me belaboring the point more than would be optimal (even after I've gone over it all again trying to drop parts where I've gotten repetitive).

I've been bitten (far) more often by the high precedence versions than the low. [...] I've racked my brains and can't reproduce anything that is a good example.

As part of reviewing stuff as part of participating in this thread, I did remember a much more recent bug that made it to Prod where it was immediately noticed and then fixed. In cleaning up some code, a construct similar to:

my $log_file = $CmdOptLogFile || $DefaultLogFile;

Ended up actually being like:

my $log_file = $CmdOptLogFile || $CmdOptViaCron ? $CronDefaultLogFile : $DefaultLogFile;

So the common use of '||' not for a Boolean expression but for providing a default value helped me to forget that '?:' expects to take a Boolean expression as its first argument and so binds more loosely than the normal Boolean operators. One could use 'or' here to avoid using parens to fix that particular problem. But now that I've said that, I realize that using 'or' would then introduce a new problem that would require adding a different set of parens (I hadn't realized that at first because when fixing the bug I didn't really consider using 'or' because this was not a case of "flow control between statements", as is my "best practice"). So, sorry for somewhat ruining my gift example. But maybe it helps you to remember an even better example.

situations where the precedence was wrong for my intent the first time I ran the code; I don't recall any occasion where it was something that I didn't discover at first run, or had any trouble locating and fixing. No latent bugs or deeply disguised issues that took any great effort to track down and fix.

My experience was mostly just finding latent bugs. They certainly were not deeply disguised and they did not take great effort to track down. They were all cases of looking at code and noticing that the real meaning of the code didn't seem to match the intent (in part because similar precedence problems were fresh on my mind). And these particular ones were all things that nobody was complaining about. The actual change in behavior due to these bugs were so rare (due to the particular combination of 2 or more conditions that had to be met for the bug to be triggered) that nobody was looking for these bugs.

But I also would not have been the one to experience "I used 'or' and then noticed I had done it wrong" because I was not using 'or' for Boolean expressions. So it isn't surprising that the only bugs I ran into were the ones that didn't cause any serious or frequent problems. But I was actually at least a bit surprised when I did find such bugs. The clincher for me was when I looked at the commit history for the most interesting bug and found that it was written by the most experienced Perl developer on the team (I'm not sure if he has more or less experience than me with Perl, though I'm pretty sure I have more programming experience just because I'm quite a bit older).

That was what switched me from "I think using 'or' for Boolean expressions is a bad idea and should be discouraged in our style guide but other team members find them prettier" to being able to make the case more strongly to get it into our style guide.

I elaborated on some stuff but reading over it again it seems rather unlikely to be of much interest. I include it below just in case some haven't heard plenty on this topic already.

I can see adopting a different mental model for precedence where one defines the use of 'and'/'or' as ordinary Boolean expressions but you put those as the first entry in your mental model of the precedence table. This would mean that you reject "assigning a Boolean expression to a variable" as a mundane construct that can avoid parens. Then one could also consider "using an assignment as a Boolean expression" as mundane (but not "using an assignment as part of a comparison"). One would also reject "using a Boolean expression as part of a list" as mundane.

I haven't spent enough time with such an idea to have much confidence myself as to how difficult or easy it would be to keep such a model consistent such that it doesn't cause conflicts with how written code actually works. But that might be part of what you have done and, if so, your experience suggests that it can work well.

I would be reluctant to go that route because I would be going against the mental model for precedence that I find evident in Perl's own precedence table. I suspect such a mental model might present more problems when it bumps up against other parts of the programming world, such as when you have to collaborate with others or when your team becomes larger or less cohesive.

I've also seen no small number of programmers who seem to consider all Boolean expressions as not mundane and prefer to put parens around them unconditionally. If you follow that practice perfectly, then the low precedence of 'or' would never present a problem. But I dislike that approach for at least a couple of reasons (I feel it goes against the evident mental model in Perl's design and I think it makes nesting of parens more likely and that leads to a significant increase in difficulty of visual parsing which makes it easy to have bugs that are hard to see). I also worry that it will be seen as "just a style choice" and so some new team member might not realize that deviating from the "parens around Booleans" style choice must also lead to deviating from the "use 'or' in Booleans" style choice.

So, I'm not particularly suspicious of your memory of '||' causing you more problems than 'or'. I suspect that keeping whatever you are doing working that way might become more difficult as collaboration increases. But I can't really say that with complete confidence. I appreciate you sharing your experience.

And I'll admit that part of my dislike of "always put parens around Boolean expressions" is due to that stance so often being accompanied by "always put parens around comparisons", a position that I dislike intensely. I have sympathy for "Boolean expressions are hard" and the instinct to add parens to clarify precedence for them, even though I find that instinct flawed. I see lots of bugs, confusion, difficulty around Boolean expressions. But I've come to feel that the precedence part is less of a contributor than, for example, subtle forms of negation. And, after decades of trying, I finally found an indentation style that I find scales well for making moderately complex Boolean expressions much easier to understand the intent of. So I have a lot of strategies for mitigating complexity with Boolean expressions and parens actually interfere with some of them and I don't see parens helping much in most situations. But I also believe that I'm in the minority in wanting to avoid extra parens in Boolean expressions.

- tye        

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (2)
As of 2022-09-28 23:03 GMT
Find Nodes?
    Voting Booth?
    I prefer my indexes to start at:

    Results (125 votes). Check out past polls.