123

Let's say I have a boolean condition a AND b OR c AND d and I'm using a language where AND has a higher order of operation precedence than OR. I could write this line of code:

If (a AND b) OR (c AND d) Then ...

But really, that's equivalent to:

If a AND b OR c AND d Then ...

Are there compelling arguments in favor or against including the extraneous parentheses?
Does practical experience suggest that including them significantly improves readability?
Or is wanting them a sign that a developer really needs to sit down and become conversant in the basics of their language?

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Jeff B
  • 838
  • 2
  • 9
  • 14
  • 94
    I may be lazy, but I prefer to have parentheses in most of such situations for readability. – thorsten müller Jun 11 '13 at 14:16
  • 6
    Me too. I'm just hoping I'm doing it more for readability and less because I'm too lazy to become confident/competent in the basics of my langauge. – Jeff B Jun 11 '13 at 14:31
  • 18
    Good usage of parentheses is like good usage of grammar. `2 * 3 + 2` might be the same as `(2 * 3) + 2` but the second is easier to read. – Reactgular Jun 11 '13 at 14:36
  • 20
    @Mathew Maybe if you’re weak in maths. For more complex cases, sure, use parentheses. But for blindingly obvious ones (BODMAS …) they *reduce* readability more than aiding it due to clutter. – Konrad Rudolph Jun 11 '13 at 21:40
  • I would expect "a AND b OR c AND d" to evaluate as left to right like "((a && b) || c) && d" so if that isn't the case: parens would be nice... – Grady Player Jun 11 '13 at 22:25
  • 2
    Just remember `&&` is times and `||` is plus, and you'll never forget which comes first. – Tim Goodman Jun 12 '13 at 01:34
  • 3
    @timgoodman, sure in c; but not in SmallTalk or psuedocode or whiteboard interview, all of which have different amorphous rules – Grady Player Jun 12 '13 at 03:04
  • 1
    @GradyPlayer, Yeah, I said `&&` and `||` instead of `and` and `or` to try to cover myself here. I think all the C-style languages are consistent about this (C, C++, Java, C#, JavaScript, ...). – Tim Goodman Jun 12 '13 at 03:27
  • 3
    That said, the same precedence of AND/OR holds in Basic, Python, SQL... my impression is that this is the rule in the vast majority of modern languages (albeit not all). – Tim Goodman Jun 12 '13 at 03:32
  • 2
    @timgoodman, good pedantism with the && equating to a c like syntax... bad pedantism if you point out that "pedantism" is a made up word – Grady Player Jun 12 '13 at 03:38
  • 3
    Don't make me think... – Gerry Jun 12 '13 at 12:39
  • 2
    Write in Lisp: unambiguous without precedence or associativity. `(or (and a b) (and c d))`. – Kaz Jun 12 '13 at 16:52
  • Yes, so you can't get confused. –  Jun 13 '13 at 08:23
  • 2
    (I (always ((bountifully include) ((technically extraneous) parenthesis))) ((in (complex (boolean expressions))) and ((complex expressions) (in general))))). – Ben Lee Jun 17 '13 at 22:15
  • I prefer comments. –  Feb 05 '14 at 04:18
  • @KonradRudolph or if you use REBOL, not all languages follow math conventions – Caridorc Aug 18 '15 at 17:59
  • @GradyPlayer - "... point out that "pedantism" is a made up word". Well, I guess you could say "pedantism" is a made up word, in the same sense that ALL words are "made up" at some point. But, pedantism is a real, valid word, although not as common as its synonyms: "pedanticism" and "pedantry". The word "pedantism" ‎(plural "pedantisms") is in many online dictionaries (including Oxford and Collins). "Behaving or acting in the manner of a pedant". Its usage dates back to at least 1601, so it's not a word that has been recently "made up". – Kevin Fegan May 14 '16 at 00:52
  • 2
    Fun fact: the programming language Ada forces you use parenthesis in logical expressions when AND and OR operators are mixed. Otherwise it’s a syntax error. – Hartmut Braun Nov 01 '21 at 18:43
  • @HartmutBraun - yes, I think it is a language design _mistake_ to have those at different precedence levels, also, mixed operators at the same precedence level should _not_ be associative at all (that would apply to the tuples (`+`, `-`) and (`*`, `/`, `%`) and (`<<`, `>>`) and other sets too in most languages. (no associativity would mean parenthesis required) – davidbak Nov 02 '21 at 17:28

15 Answers15

142

Good developers strive to write code that is clear and correct. Parentheses in conditionals, even if they are not strictly required, help with both.

As for clarity, think of parentheses like comments in code: they aren't strictly necessary, and in theory a competent developer should be able to figure out code without them. And yet, these cues are exceedingly helpful, because:

  • They reduce the work required to understand the code.
  • They provide confirmation of the developer's intent.

Furthermore, extra parentheses, just like indentations, whitespace, and other style standards, help visually organize the code in a logical way.

As for correctness, conditions without parentheses are a recipe for silly mistakes. When they happen, they can be bugs that are hard to find--because often an incorrect condition will behave correctly most of the time, and only occasionally fail.

And even if you get it right, the next person to work on your code may not, either adding errors to the expression or misunderstanding your logic and thus adding errors elsewhere (as LarsH rightly points out).

I always use parentheses for expressions that combine and and or (and also for arithmetic operations with similar precedence issues).

  • 3
    Although, I've heard it said comments are apologies (for bad/hard-to-read code)... there's a good chance you could have written it better. I guess you could say a similar things about parentheses. – Jeff B Jun 11 '13 at 21:05
  • 9
    Another aspect of correctness is preserving it through changes: While the original developer may get precedence right without parentheses when he first writes the code with the purpose and context fresh in mind, he (or another) who comes along later and doesn't remember all the details may well mess it up when they add more terms to the expression. (That was mostly implied already but I felt like it was worth emphasizing.) – LarsH Jun 12 '13 at 13:33
  • 1
    @LarsH, thanks, I added this explicitly to the answer. –  Jun 12 '13 at 13:36
  • 12
    +1 "They provide confirmation of the developer's intent." - any programmer (OK, maybe not all, but all of those that reside here....) can work out what the compiler will do with the most complex logic. Absolutely no one can work out what the original developer intended (Including himself) a few weeks down the track for anything beyond the simplest..... – mattnz Jun 14 '13 at 03:24
  • 3
    I think @JeffBridgman was referencing a fairly well known standpoint of "comments can **sometimes** be a code smell". E.g. see [Jeff Atwood's summary](http://www.codinghorror.com/blog/2006/05/code-smells.html) which includes the question "Can you refactor the code so the comments aren't required?". I'd argue that if your comment is explaining why your code is so damn un-intuitive, it can definitely be a hint that something's wrong. At times like this, it's a good idea to simplify the code. I completely agree with your actual answer though and take on parentheses, however. – Daniel B Jun 14 '13 at 11:18
  • 1
    I wonder, is it also OK to write like this: `&(somePointer->someValue)` ? From one hand, a programmer should know that & (address) has higher precedence than `->`, but from the other hand I find it more readable, later when I fast-read my code to check if I haven't done something silly. – JustAMartin Jan 31 '17 at 09:03
  • The reader may know the precedence, but the reader cannot know whether _you_ know the precedence. Take the expression "a & b + c". I seriously don't _care_ what the precedence is, because I can figure out what the expression does, but I can't figure out what it is meant to do. – gnasher729 Nov 01 '21 at 13:58
  • A good developer aims to bring other developers up to his level of knowledge - this doesn't happen if his code is filled with redundant brackets which he knows are redundant but they don't. I've seen the same argument made for "don't use `Flags` enums because people might not know what they are" - I say "do use `Flags` enums, if appropriate, as people might not know what they are and learn something as a result". – Matt Arnold Feb 07 '22 at 12:40
95

It matters less whether you are confident in your grasp of the language. What matters more is the grasp of the language of the n00b that follows you.

Write your code in the clearest most unambiguous way possible. Extra parenthesis often (but not always) help. Putting only one statement on a line often helps. Consistency in coding style often helps.

There is such a thing as too many parenthesis, but it's one of those situations where you won't need advice - you'll know it when you see it. At that point refactor your code to reduce the complexity of the statement rather than remove parenthesis.

eadsjr
  • 103
  • 3
Dan Pichelman
  • 13,773
  • 8
  • 42
  • 73
  • 1
    Yea, the 'novice developer' that follows was a concern as well... – Jeff B Jun 11 '13 at 14:47
  • 76
    Don't forget that even if you're a solo developer when ill, tired, or dealing with code you wrote last year; your comprehension level is reduced to that of a n00b. – Dan Is Fiddling By Firelight Jun 11 '13 at 16:01
  • 36
    `There is such a thing as too many parenthesis` -- you're obviously not a lisper ;) – paul Jun 11 '13 at 17:12
  • the language rules that and is stronger than or is very arbitrary, easy to overlook both in reading and writing – Balog Pal Jun 11 '13 at 18:07
  • @Paul - you are correct :-) – Dan Pichelman Jun 11 '13 at 19:03
  • Simply mentioning coding consistency gets you a +1... – Radu Murzea Jun 11 '13 at 20:06
  • 20
    That’s bad advice: **Do not** write for noobs. This will *reduce* your code quality (considerably) because you cannot use well-established idioms that go beyond the first two chapters of a beginner’s book. – Konrad Rudolph Jun 11 '13 at 21:41
  • @DanNeely: f\*ck last year, I can't remember what I did at the beginning of the month already! :) – haylem Jun 11 '13 at 23:18
  • 10
    @KonradRudolph: maybe so, but don't write for the only guys who know the Art of Computer Programming from cover to cover either, or be prepared to have to debug their code afterwards, and not have a clue why you did things that way. Code is read a lot more than it's written. – haylem Jun 11 '13 at 23:20
  • 3
    @haylem: Really? Only people who know TAOCP cover-to-cover know the precedence rules of Boolean algebra? It's not like the latter was invented yesterday, or even in 1975 along with C. This is basic stuff that anyone who's taken Computer Science 101 should know cold. – dodgethesteamroller Jun 12 '13 at 04:37
  • 16
    @dodgethesteamroller: I've seen far too many competent/respected developers introduce precedence bugs (everyone has a bad day now and then) that remain unnoticed for ages. For good developers who do know the precedence rules, the risk of undetected mistakes/typos is too high. For everyone else the risk is higher. The best developers are the developers that used to remember the language's precedence rules, but forgot them due to habitually using parenthesis for anything non-obvious. – Brendan Jun 12 '13 at 05:09
  • 1
    So that legions of N00Bs might read your code, you should use `i = i + 1` and never cryptic stuff like `i++`. :) – Kaz Jun 12 '13 at 07:47
  • 4
    @dodgethesteamroller: that's not at all what I said. Konrad made a general statement, that I addressed. And you'd be surprised the number of basic stuff people do not know. And even when you do know them, everybody makes mistakes. But hey, feel free to think your and your team are above that and to code for the ideal developer. I hope it doesn't bite you in the bottom. – haylem Jun 12 '13 at 10:23
  • 1
    @Kaz, `i = i + 1` is valid syntax in (almost) every language that I know of. While many support `i++`, not all of them do (VB & Python being two that I know of that don't. So I usually write `i = i + 1`. Also, you never have to remember if it increments and then uses the value, or uses the value and then increments ;) – Wayne Werner Jun 12 '13 at 13:14
  • @Dan:Just remove the entire first paragraph, since noob raised objections by several people, and I don't agree with a blanket "confident in your grasp of language" because Brendan hit the nail on the head with his "best developers used to remember...habitually using parenthesis for anything non-obvious". If you get rid of that paragraph then you have the definitive answer. – Dunk Jun 12 '13 at 18:35
  • @Dunk personally I think "write code for a n00b" is a fantastic general rule. The n00b might be *you* in the future, but it's useful to have a succinct general rule to remember and apply (rather than having to memorise 2 paragraphs), and "write code for a n00b" is a very good one. – Robin Winslow Jun 19 '13 at 08:17
  • I like the statement of "dont make me think". Not using parentheses does require one to slow down to read the statements and process them in their head to determine the logic. I honestly dont get why there are many who object to code clarity and intentions and really want to simplify code to the minimal number of keystrokes. The next guy to see your code needs to get to a level of understanding quickly so that they can get on to what they are really trying to do. Cryptic, unreadable code is not maintainable and is definitely a code smell. – FrankO Nov 08 '18 at 19:04
34

Yes

You should always use parentheses... you do not control the order of precedence... the developer of the compiler does. Here is a story that happened to me about non use of parentheses. This affected hundreds of people over a two week period.

Real World Reason

I inherited a main-frame application. One day, out of the blue, it stopped working. That's it... poof it just stopped.

My job was to get it working as fast as possible. The source code had not been modified for two years, but all of the sudden it just stopped. I tried to compile the code and it broke on line XX. I looked at line XX and I could not tell what would make line XX break. I asked for the detailed specs for this application and there were none. Line XX was not the culprit.

I printed out the code and started reviewing it from the top down. I started to create a flowchart of what was going on. The code was so convoluted I could hardly even make sense of it. I gave up trying to flowchart it. I was afraid to make changes without knowing how that change would effect the rest of the process, especially since I had no details of what the application did or where it was in the dependency chain.

So, I decided to start at the top of the source code and add whitespace and line breaks to make the code more readable. I noticed, in some cases, there were if conditions that combined AND and OR statements and it wasn't clearly distinguishable what data was being ANDed and what data was being ORed. So I started putting parentheses around the AND and OR conditions to make them more readable.

As I slowly moved down cleaning it up, I would periodically save my work. At one point I tried compiling the code and a strange thing happened. The error had jumped passed the original line of code and was now further down. So I continued, separating the AND and OR conditions with parens. When I got done cleaning it up it worked. Go figure.

I then decided to visit the operations shop and ask them if they had recently installed any new components on the main-frame. They said yes, we recently upgraded the compiler. Hmmmm.

It turns out that the old compiler evaluated expressions from left to right regardless. The new version of the compiler also evaluated expressions from left to right but ambiguous code, meaning unclear combinations of AND and OR could not be resolved.

Lesson I learned from this... ALWAYS, ALWAYS, ALWAYS use parens to separated AND conditions and OR conditions when they are used in conjunction with each other.

Simplified Example

`IF Product = 191 OR Product = 193 AND Model = "ABC" OR Product = 201 OR Product = 202 AND Model = "DEF" ...` (code littered with several of these)

This is a simplified version of what I encountered. There were else conditions with compound boolean logic statements as well.

I remember changing it to:
`IF ((Product = 191 OR Product = 193) AND Model = "ABC") OR ((Product = 201 OR Product = 202) AND Model = "DEF") ...`



I couldn't rewrite it because there were no specs. The original author was long gone. I remember intense pressure. An entire cargo ship was stranded in port and could not be offloaded because this little program did not work. No warning. No changes to the source code. It only dawned on me to ask the Network Operations if they modified anything after I noticed that adding parens shifted the errors.

  • Excellent real life illustration of why to do this! – Jordan Jun 11 '13 at 19:25
  • 25
    That seems like a better illustration of why it's important to have a good compiler. – ruakh Jun 11 '13 at 19:35
  • @ruakh - Didn't have a choice. I worked for the DOD and it was an IBM Mainframe programming language compiler called Natural written by Software AG. – Michael Riley - AKA Gunny Jun 11 '13 at 20:45
  • 7
    @CapeCodGunny: I'm sure you didn't. But the problem here is that you had a bad compiler vendor that made a breaking change. I don't see how you learned a lesson to "ALWAYS, ALWAYS, ALWAYS" work around that problem, even when using better compilers. – ruakh Jun 11 '13 at 20:55
  • 5
    @ruakh - No, the vendor simply changed their code parser. I'm old school, I don't rely on my ability to remember every system I've coded or been involved in. Without documentation all you have is the source code. When the source code is difficult to read and follow it creates an extremely stressful situation. Programmers who don't use whitespace have probably never had to deal with a situation like the one I was faced with. I also learned that it makes more sense to write code like: See Dick; See Jane; See Dick AND Jane; Simple statements that are easy to read... comment out... and follow. – Michael Riley - AKA Gunny Jun 11 '13 at 22:06
  • 3
    Great story, but I agree that it is not a reason to use parentheses. and/or precedence is nearly universal and about the least likely thing to change that one could think of. If you can't rely on consistent behavior for such a standard, basic operation, your compiler is garbage and you are hosed no matter what you do. Your story is 100% a compiler problem and 0% a code problem. Especially given that the default behavior was simple left-to-right evaluation--order would always be clear, so why would anyone use parentheses? –  Jun 12 '13 at 12:54
  • @dan1111 - The compiler was an IBM Mainframe product called Natural written by Software AG http://www.softwareag.com/natural/ . I honestly have no idea what the order of precedence was are far as combined ANDs and ORs on the same line. I'll update my answer and add an example of the complex boolean logic that was used. – Michael Riley - AKA Gunny Jun 12 '13 at 13:20
  • @CapeCodGunny, sorry, I misunderstood what you said then, regarding the precedence. –  Jun 12 '13 at 13:27
  • 7
    I think there are lessons learned here on both sides... You're much better off using parentheses **especially when the alternative is relying on the undocumented behavior of a compiler in regard to ambiguous code**. And if the programmer doesn't know which expressions are ambiguous, better use parens. On the other side, it's dangerous to change the behavior of a compiler, but at least it threw an error in cases where behavior changed. It would have been worse if the compiler had *not* thrown an error, but had begun compiling differently. The error protected you from unnoticed bugs. – LarsH Jun 12 '13 at 13:38
  • 1
    @LarH Programming languages in 2013 should not have undocumented ambiguities with regard to syntactic issues like operator precedence. This is covered by the overriding principle of not selecting crap tools for the project. – Kaz Jun 12 '13 at 16:48
  • @Kaz - "**should not** have undocumented ambiguities".... You can guarantee that? Or that an breaking change on parsing/syntax checking/code generation will not happen? Of course not. So LarsH and CapeCodGunny are right: be clear on the intentions when writing conditional statements. – Fabricio Araujo Jun 12 '13 at 19:26
  • 1
    @FabricioAraujo Yes, I can guarantee that any mainstream implementation of some "modern" language (C++, Java, C#, Python, you name it) either has its operator precedence fully documented and working according to the document. The idea that you write A op1 B op2 C and not know from the spec whether it is (A op1 B) op2 C or A op1 (B op2 C), or to have the compiler/interpreter implement it contrary to the spec, is just unheard of. This kind of issue is an earmark of a very new language in its early stages of development. (No users, no rigorous spec, no regression test suite ...) – Kaz Jun 12 '13 at 19:48
  • @Kaz: you know that exists miles of distance between "should not have" and "does not have". – Fabricio Araujo Jun 13 '13 at 14:17
  • 2
    @FabricioAraujo Not always, sometimes only millimeters of distance. Anyway, if you don't trust your compiler to get precedence right, why do you trust it to get parentheses right? How do you know that the parenthesis does not have an undocumented ambiguity? How do you know that it's reliably able to overcome an undocumented ambiguity? – Kaz Jun 13 '13 at 15:58
  • 1
    @Kaz: Because of experience. Parenthesis is more reliable than using the precedence and (using well) transmit my intention much better. And yet, many times I decompose long boolean sentences on boolean variables (where available, when not I do the most common idiom to emulate them) much before **introduce local** refactoring became common on IDEs. – Fabricio Araujo Jun 13 '13 at 18:48
  • 1
    This is an interesting tale, but to my mind it also (and even more than being about parenthesis) shows how important it is to **not make changes to critical production systems without proper stage testing**. Any proper test procedure before upgrading that completely essential piece of software would have caught this error immediately, and it would not have been an issue because the problem with the code could almost certainly have been fixed while under no pressure to speak of. – user Jun 27 '13 at 14:15
  • Interestingly enough, the proof is in the pudding; your example's first (unparenthesized) example was a headache; the second was much clearer. – Qix - MONICA WAS MISTREATED Dec 06 '14 at 04:48
  • @Gunny Thanks for taking the time to share that real-world experience. Fantastic. – Mark Goldfain Oct 19 '18 at 02:58
  • That is just awful. A compiler change that changes the meaning of code? Someone needs to be shot. Your only choice: Take two developers. You both take the source code, and independently add parentheses around all your ANDs so that the new compiler will produce the same results as the old one. And then you compare until you both agree. And that's your new code. And make sure everything is tested. – gnasher729 Nov 01 '21 at 14:03
  • If a decent compiler ever had to make such a change, it would give you a big fat warning for every place where the old compiler and new compiler give you different results. – gnasher729 Nov 01 '21 at 14:06
  • "I couldn't rewrite because there was no spec" - the code ran for two years without any complaints when compiled with the old compiler. So you change it in a way that it does the same thing with the new compiler that it used to do with the new one. – gnasher729 Nov 01 '21 at 14:08
  • @gnasher729 I guess technically it was an interpreter not a compiler because it ran the source code when called. It did not execute a compiled module. – Michael Riley - AKA Gunny Nov 02 '21 at 20:02
19

Yes, if there are mixed 'and' and 'or'.

Also good idea to () what is logically one check.

Though best is to use well-named predicate functions and evict most checks and conditions there, leaving if simple and readable.

Balog Pal
  • 1,711
  • 9
  • 16
  • 6
    True, there's a very good chance `a AND b` probably should be replaced with either a function or pre-calculated boolen value that has a more descriptive name. – Jeff B Jun 11 '13 at 14:30
17

The parentheses are semantically redundant, so the compiler doesn't care, but that's a red herring--the real concern is programmer readability and comprehension.

I'm going to take the radical position here and give a hearty "no" to the parentheses in a AND b OR c AND d. Every programmer should know by heart that precedence in Boolean expressions goes NOT > AND > OR, just like remembering Please Excuse My Dear Aunt Sally for algebraic expressions. Redundant punctuation just adds visual clutter most of the time in code with no benefit in programmer readability.

Also, if you always use parentheses in logical and algebraic expressions, then you give up the ability to use them as a marker for "something tricky is happening here--look out!" That is, in the cases where you want to override default precedence and have addition evaluated before multiplication, or OR before AND, parentheses are a nice red flag to the next programmer. Too much use of them when they're not needed, and you become the Boy Who Cried Wolf.

I would make an exception for anything outside the realm of algebra (Boolean or not), such as pointer expressions in C, where anything more complicated than standard idioms like *p++ or p = p->next probably ought to be parenthesized to keep the dereferencing and the arithmetic straight. And, of course none of this applies to languages like Lisp, Forth, or Smalltalk that use some form of Polish notation for expressions; but for the majority of mainstream languages, logical and arithmetic precedence are totally standardized.

  • 1
    +1, parentheses for clarity are fine, but `AND` vs `OR` is a fairly basic case which I would want the other devs on my team to know. I worry that sometimes "using parentheses for clarity" is really "using parentheses so I never have to bother to learn the precedence". – Tim Goodman Jun 12 '13 at 13:40
  • 1
    In all the languages I work with regularly it's `.member` before unary operators, unary before binary operators, `*` and `/` before `+` and `-` before `<` and `>` and `==` before `&&` before `||` before assignment. Those rules are easy to remember because they match my "common sense" about how the operators are normally used (e.g., you wouldn't give `==` greater precedence than `+` or `1 + 1 == 2` stops working), and they cover 95% of the precedence questions I'd have. – Tim Goodman Jun 12 '13 at 13:48
  • 4
    @TimGoodman Yes, exactly right, to both your comments. Other responders here seem to think it's a black or white question--either use parentheses all the time, no exceptions, or fly carelessly by the seat of your pants through a sea of arbitrary and impossible-to-remember rules, your code boiling over with potential hard-to-spot bugs. (Mixed metaphors very intentional.) Obviously the right way is moderation; code clarity is important, but so is knowing your tools well, and you should be able to expect a certain minimum understanding of programming and CS principles from your teammates. – dodgethesteamroller Jun 12 '13 at 19:57
9

As I see it:

YES Pros:

  • Order of operations is explicit.
  • Protects you from future developers who don't understand order of operations.

YES Cons:

  • May result in cluttered, difficult to read code

NO Pros:

  • ?

NO Cons:

  • Order of operations is implicit
  • Code is less maintainable for developers without a good understanding of order of operations.
MetaFight
  • 11,549
  • 3
  • 44
  • 75
  • Well said, though I think *"May result in cluttered, difficult to read code"* is rather subjective. – FrustratedWithFormsDesigner Jun 11 '13 at 14:42
  • 2
    How does making the semantics of your code explicit make it difficult to read? – Mason Wheeler Jun 11 '13 at 14:44
  • 1
    I agree with the others in questioning your "Yes Cons". I think it is almost always the opposite. –  Jun 11 '13 at 14:56
  • @Frustrated As subjective as the opposite claim. Meaning, not at all, really. Just hard to measure. – Konrad Rudolph Jun 11 '13 at 21:40
  • 1
    @MasonWheeler: While I agree that explicit parens are very important in many cases, I can see how one can go overboard on making semantics explicit. I find `3 * a^2 + 2 * b^2` easier to read than `(3 * (a^2)) + (2 * (b^2))`, because the format and precedence is familiar and standard. Likewise, you could (to be extreme) forbid the use of functions and macros (or compilers!) in order to make the semantics of your code more explicit. Obviously I'm not advocating that, but I'm hoping to answer your question as to why there need to be limitations (a balance) on making things explicit. – LarsH Jun 12 '13 at 13:45
  • Other ways to write this, that I find easier to read: `3*a^2 + 2*b^2` or `(3 * a^2) + (2 * b^2)` -- mostly a personal preference/habit though. – Droopycom May 03 '18 at 19:49
3

General case

In C#, multiplication and division has a precedence over addition and subtraction.

Still, StyleCop, a tool which enforces common style across the codebase with an additional goal to mitigate the risk of bugs introducing by code which may not be clear enough, has the rule SA1407. This rule will produce a warning with a piece of code like this:

var a = 1 + 2 * 3;

It's clear that the result is 7 and not 9, but still, StyleCop suggests to put parenthesis:

var a = 1 + (2 * 3);

Your particular case

In your particular case, there is a precedence of AND compared to OR in the particular language you use.

This is not how every language behave. Many others treat AND and OR equally.

As a developer who works mostly with C#, when I saw your question the first time and read the piece of code without reading what you've wrote before, my first temptation was to comment that the two expressions are not the same. Hopefully, I've read the whole question entirely before commenting.

This particularity and the risk that some developers may believe that AND and OR have the same priority makes it even more important to add parenthesis.

Don't write code with a goal to show that you're smart. Write code with a goal of readability, including by people who may not be familiar with every aspect of the language.

Arseni Mourzenko
  • 134,780
  • 31
  • 343
  • 513
  • 2
    "This is very uncommon": According to Stroustrup2013, C++11 seems to have different precedence of AND and OR (p. 257). Same for Python: http://docs.python.org/2/reference/expressions.html – Dirk Jun 11 '13 at 19:26
  • 11
    Re: "Every language I know treat AND and OR equally": I doubt that's true. If it *is* true, then you don't know *any* of [the ten most popular languages](http://www.langpop.com/) (C, Java, C++, PHP, JavaScript, Python, C#, Perl, SQL, and Ruby), and are in no position to be commenting on what is "uncommon", let alone "very uncommon". – ruakh Jun 11 '13 at 19:34
  • 1
    I agree with ruakh and looked it up for C++11, python, matlab and java. – Dirk Jun 11 '13 at 19:36
  • 1
    @ruakh: thank you for your comment. Indeed, I haven't thought enough about different languages. I edited the answer. – Arseni Mourzenko Jun 11 '13 at 19:44
  • … not to mention the difference in C++ and Perl between && || and "and" "or" … – BRPocock Jun 11 '13 at 21:48
  • 1
    "Many others treat AND and OR equally." Really? "Many"? How many can you list? Two? Three? – dodgethesteamroller Jun 12 '13 at 04:39
  • 3
    Languages in which AND and OR are binary operators, and which do not treat AND as having a higher precedence than OR, are braindamaged crap whose authors are computer science flunkies. This comes from logic notation. Hello, does "sum of products" not mean anything? There is even a boolean notation which uses multiplication (juxtaposition of factors) for AND, and the + symbol for OR. – Kaz Jun 12 '13 at 07:53
  • @dodgethesteamroller: Dude, you can find a language with any property you can think of. In this case -- Pascal, ALGOL 58, FORTRAN 77, and some parts of the POSIX shell. (Note that in the cases of ALGOL and FORTRAN, newer standards fixed this deficiency, and in the case of the POSIX shell, newer parts of the language have chosen to be inconsistent with the deficiency. Pascal is the only language that seems to have really *wanted* "and" and "or" to have the same precedence.) – ruakh Jun 12 '13 at 18:27
  • 3
    @ruakh You just made my point for me. Because there are a handful of pathological edge cases doesn't mean that you shouldn't learn standard Boolean precedence and assume it holds until proven otherwise. We're not talking about arbitrary design decisions here; Boolean algebra was invented long before computers. Also, show me the Pascal spec you're talking about. [Here](http://www.freepascal.org/docs-html/ref/refch12.html) and [here](http://montcs.bloomu.edu/~bobmon/Information/operator-precedence.C-Python-Pascal.shtml) show AND before OR. – dodgethesteamroller Jun 12 '13 at 19:51
  • @dodgethesteamroller: Well, I made the point before you did, so I don't think you can call it *your* point! :-) (See my comment five above yours.) . . . Re: Pascal: Oops, you're right. I was looking at `or else` vs. `and also`, rather than bare `or` vs. `and`. – ruakh Jun 12 '13 at 21:00
  • These "code quality checkers" are often do not possess high quality themselves so you have to go and manually disable 3/4 of the checks. These checks are just random checks that somebody decided they can be of use in some occasions. There are usually no statistically-based evidences of any sort as you would assume. – konmik Jan 27 '20 at 21:43
3

Are there any arguments in for or against including the extraneous parentheses? Does practical experience suggest that it is worth including them for readability? Or is it a sign that a developer needs to really sit down and become confident in the basics of their language?

If no one else ever would have to look at my code again, I do not think I would care.

But, from my experience:

  • I look at my code again occasionally (sometimes years after writing it)
  • Others sometimes look at my code
    • Or even have to expand/fix it!
  • Neither myself or the other remembers exactly what I was thinking when writing it
  • Writing cryptic "minize the character count" code hurts readability

I almost always do this because I trust my ability to quickly read and not make little mistakes a lot more with parens than nothing else.

In your case, I would almost assuredly do something like:

if (a AND b) then ab = true
if (c AND d) then cd = true
If (ab OR cd) Then ...

Yes, it's more code. Yes, I can do fancy bool operators instead. No, I don't like the chance when skimming code 1+ years in the future I misread fancy bool operators. What if I was writing code in a language which had different AND/OR precedence and had to jump back to fix this? Am I going to go, "aha! I remember this clever little thing which I did! I didn't have to include parens when I wrote this last year, good thing I remember now!" if that happens (or worse, someone else who wasn't aware of this cleverness or was thrown into a "fix asap" type situation)?

Separating with () makes it so much more straightforward to quickly skim and understand later...

enderland
  • 12,091
  • 4
  • 51
  • 63
1

As everyone said, use parentheses everytime it makes the expression more readable. However if the expression is complicated I'd advise to introduce new functions for the subexpressions.

Honza Brabec
  • 602
  • 4
  • 11
0

Or is it a sign that a developer needs to really sit down and become confident in the basics of their language?

If you strictly use language in singular, maybe. Now take all the languages you know, from ages old to most modern, from compiled to scripting to SQL to your own DSL you've invented last month.

Do you remember the exact precedence rules for each of these languages, without looking?

Secure
  • 1,918
  • 12
  • 10
  • 1
    And as @Cape Cod Gunny above noted, even if you think you know the language cold, the compiler/run-time might change below you. – Jordan Jun 11 '13 at 19:26
  • @Jordan That depends on the language. If it is an esoteric homebrew, or pre-alpha, it might. If it is undocumented, how would you know what is by design, what is a bug, and what happens because it's tuesday? Somewhat mature languages, especially if standardized or at least ubiquitous? Outside the really dark corners, get real. – Deduplicator Nov 02 '21 at 16:01
0

I will use parenthesis even if it is optional, why because it helps to better understand for everyone, for the one who write the code as well as the one ready to see that code. In your case even the boolean operators have precedence it might work well at first, but we can't say it will help you in every case. so i prefer to user parenthesis in any condition that it may require it or optionally.

0

"Should I use parentheses in logical statements even where not necessary."

Yes, because two people will find them helpful:

  • The next programmer, who's knowledge, competency or style may be different

  • The future you who returns to this code at some later date!

Michael Durrant
  • 13,101
  • 5
  • 34
  • 60
0

Yes. You should use in any case when you feel your code will be more clear. Remember your code should be clear enough so that others can understand without reading your comments inside the code. So it is a good practice to use parentheses and braces. Also keep in mind that it may be depends on the particular practice of your company/team. Just maintain one approach and do not mix.

Arnab
  • 377
  • 1
  • 2
  • 10
0

• I just got back from your funeral. (Sorry about that bread truck, pal ...)

• Or maybe, you just don't work here anymore, and you've changed your phone number.

• I have never seen your code before. Among tens of millions of lines of stuff, I just encountered yours.

• The fires of business urgency are breathing down my neck. "Pres-sure!"

• So ...

"Anything that you can do to make your code more clear(!) is priceless!"

• Because, "here's what keeps me up at night, because it's cost me a lot of sleep and my employer a lot of money." I glance at a line of code, think that I understand what it is doing, but I am wrong. "This WAS the bug that I was looking for, and I just missed it."

• Therefore, "please write your code stupid-simple clear, and accompany it with lots of comments. Thank you very much. "The compiler or interpreter doesn't care either way, but I do, because I have to!"

• My all-too-often pounded forehead will also thank you. "D'oh" is not something that I wish to say!

Mike Robinson
  • 1,765
  • 4
  • 10
-1

Complex conditionals are "boolean algebra", which you write in some ways that, well, make it look pretty much exactly like algebra, and you'd definitely use parens for algebra, wouldn't you?

The really useful rules are the negation ones:

!(A || B) <=> !A && !B
!(A && B) <=> !A || !B

Or, in a little clearer format:

!(A + B) <=> !A * !B
!(A * B) <=> !A + !B

which is really clearly just algebra when written as:

-1*(A + B) = -A + -B
-1*(A * B) = -A * -B

But we can also apply the thinking for algebraic simplification and expansion:

(A && B) || (C && D) => 
((A && B) || C) && ((A && B) || D) => 
(AC && BC) && (AD && BD) =>
AC && BC && AD && BD

although in code you have to write:

(A||C) && (B||C) && (A||D) && (B||D)

or, in a little clearer format:

(A + B) * (C + D) => 
((A + B) * C) + ((A + B) * D) => 
(AC + BC) + (AD + BD) =>
AC + BC + AD + BD

Basically, a conditional is still just an algebraic expression, and by clearly using parenthesis, you can more easily apply the various algebraic rules you already know to the expression, including ye olde concept of "simplify or expand this formula".

Narfanator
  • 222
  • 2
  • 6
  • 2
    I'm not sure you're actually answering the question, since you lead your answer with an assumption that isn't necessarily true. Would I use parentheses for algebra? Not all the time. If it helps with readability, then certainly, but others have already expressed that here. And expanding mathematic algebra into other forms doesn't exactly have a one-to-one correspondence to programming - what if you are checking the status of a few string values? – Derek Jun 11 '13 at 19:46
  • If the corresponding boolean algebra is complicated enough to warrant parens, your conditional should probably use parens. If it's simple enough not to warrant parens, you either don't have to, or shouldn't. Either way, thinking of it as you would a mathematical expression probably clarifies the issue. – Narfanator Jun 11 '13 at 20:09
  • My examples above use two and four booleans. If you're checking the status of two or more string values, it maps. Each check corresponds to one boolean variable; regardless of whether that check is integer or string equality; string, array or hash inclusion; a complex expression itself... Doesn't matter; all that matters is you've got *more than one* measurement of true/false in your expression. – Narfanator Jun 11 '13 at 20:13
  • 2
    Just nitpicking, but in `!(A + B) <=> !A + !B` and `-1*(A + B) = -A + -B` shouldn't the operator have been flipped from `+` to `*` in the second expression? – Jeff B Jun 11 '13 at 21:18
  • I agree: "in the pressure of the moment, don't make me CARE about "Boolean Algebra" when you could have pressed the "(" and ")" keys just a few more times and made both your logic and your intentions perfectly CLEAR to your anonymous successor ... another person whom you will never meet, but whose back is probably against the wall. – Mike Robinson Nov 02 '21 at 15:40