68

Languages like C, Java, and C++ all require parenthesis around an entire expression when used in an if, while, or switch.

if (true) {
    // Do something
}

as opposed to

if true {
    // Do something
}

This seems odd to me because the parenthesis are redundant. In this example, true is a single expression on its own. The parenthesis do not transform its meaning in any way I know of. Why does this odd syntax exist and why is it so common? Is there a benefit to it I'm not aware of?

Velovix
  • 773
  • 20
    Pascal doesn't require parentheses (because it requires a THEN). – JimmyB Nov 07 '16 at 09:16
  • @JimmyB: Indeed, see my comment to Telastyns answer. :-) – Ulrich Gerhardt Nov 07 '16 at 10:16
  • 32
    Python, Ruby don't. – smci Nov 07 '16 at 12:29
  • 2
    To sepearte the test part of the if and the subsequent, action, part. – Mawg says reinstate Monica Nov 07 '16 at 13:41
  • Isn't it just because in C you use parenthesis for all functions and "IF()" kind of is a function? – Pieter B Nov 07 '16 at 13:59
  • 33
    I believe C uses parentheses because the braces are optional for a single-statement body. Or perhaps a better way to put it is that the braces aren't part of the if statement, they just create a compound statement. – Fred Larson Nov 07 '16 at 14:54
  • 7
    Go, interestingly, requires braces but not parentheses. – Kos Nov 07 '16 at 15:31
  • One reason is that it makes the code a lot easier for humans to read. Likewise grouping the conditions with multiple parens - e.g if ((a > b) || (c < d)) - to make your intent perfectly clear to both human & compiler. – jamesqf Nov 07 '16 at 17:05
  • As an example, in C "if x + 1 ;" would be ambiguous. Could be "if (x) +1;" or "if (x + 1) ;". – gnasher729 Nov 07 '16 at 17:21
  • 2
    Plenty of languages don't - you can add Ada, VHDL, the Modula and Algol families to that list. C does require it - originally, to keep the parser simple - and some languages do the same just because C did. – user_1818839 Nov 07 '16 at 17:29
  • 1
    Why does this odd syntax exist and why is it so common? This sounds highly subjective because I cannot imagine that it's so odd if it's gained widespread usage. – MonkeyZeus Nov 07 '16 at 21:16
  • 25
    The question is a little bit tautological. Why are round manhole covers all round? Why are all brothers male? Why do paren-requiring-languages all require parens? Round manhole covers are round by definition; brothers are male by definition; languages which require parens require parens by definition. – Eric Lippert Nov 07 '16 at 21:19
  • 2
    @EricLippert If the question is restricted to C and C-derived languages, there is a syntactic reason (the one already given). This would even give a historical reason of why parens might still be required for a C-derived language that does not allow ifs with no braces. So, it would be slightly closer to the "round manhole cover" example than the others (there is the tautological answer since "round" is specified, but manhole covers are usually round because, among other reasons, a circular cover will not accidentally fall into the hole when removed). – David Nov 07 '16 at 21:34
  • C does it because the C designers decided to do it that way. C++ does it because C++ was intended to be bug-compatible with C. Java did it because the Java designers copied C, presumably because they knew what would happen if they copied PASCAL. Any language that copied C will do it that way. As other have pointed out, ALGOL, PASCAL, Modula/Modula-2/Modula-3, Ada, and VHDL do not do it that way. – John R. Strohm Nov 08 '16 at 01:32
  • 1
    @John R. Strohm: But IIRC Fortran does require parens (or at least all the code I've seen uses them), so I wouldn't be surprised to find that C inherited the usage from it. The real question, IMHO, is why they didn't require them around the value of a return statement. I've always written "return (value);" rather than "return value;", and find it a little annoying that some people don't. – jamesqf Nov 08 '16 at 03:46
  • @jamesqf That gets into the "semicolon as separator" vs. "semicolon as terminator" discussion. C and its descendants use semicolons to terminate statements. PASCAL and its descendants GENERALLY use semicolons to separate statements. (Ada is the exception: Although descended from PASCAL, it uses semicolons to terminate statements.) – John R. Strohm Nov 08 '16 at 03:52
  • 1
    @jamesqf The original FORTRAN IF-statement was very different from what you are used to seeing in C and PASCAL code. Recall that FORTRAN did not have reserved words, at all. – John R. Strohm Nov 08 '16 at 03:54
  • 1
    Swift doesn't require it. It's Apple's way of making their code just that much thinner. – Fine Man Nov 08 '16 at 07:47
  • 1
    It does no harm, and it makes it easier for humans and editors to see what's what.. – Lenne Nov 08 '16 at 22:50
  • @John R. Strohm: I don't quite date back to original FORTRAN. Mostly F77, some F66 that I was being paid to rewrite without things like assigned & computed GOTOs. I don't recall any IFs or other control statements (other than GOTO) that didn't use parens, but that could just be my memory. – jamesqf Nov 09 '16 at 05:47
  • remember that in some languages objects can be declared anonymously. Which means that brackets are not sufficient as a delimiter. Exp. 'For (i) {' the parenthesis are redundant, but 'For ({ sub1:5, sub2:13}) {' the parenthesis are not redundant. If you didn't have them the meaning would be totally lost. Now, this is an edge case, but it shows one of the reasons that parenthesis can be necessary. – EvSunWoodard Nov 09 '16 at 15:14
  • @EricLippert manhole covers have to be round, or else a truck driving over one could dislodge it, and if any point on the outside was smaller than the inside, it would fall in. That is the definition of a circle. So, the properties of a circle dictate the required shape, it is not a matter of words or definition (a tautology) - it is a functional requirement. Perhaps, in a similar way, if a truck drove over some C, some of the code would fall in to a hole and so the solution is to use round things to keep that from happening? This is not an argument over naming. –  Nov 10 '16 at 14:28
  • @nocomprende: Some manhole covers are shapes other than circles, and have other mechanisms that prevent them from falling into the hole. We're perfectly capable of engineering multiple solutions to this problem. My point is that the question "why are round manhole covers round?" presupposes that they're round; one does not need to provide an engineering requirements explanation to answer that question; the question answers itself. – Eric Lippert Nov 10 '16 at 14:36
  • @EricLippert but simply making them round solves the problem in the easiest way. I think the answer is the same for using parentheses. "Everything should be made as simple as possible, but not simpler" as Albert Einstein said. So they are round because a smart person decided that was simplest. Does making something simple require any further discussion? –  Nov 10 '16 at 14:40
  • @nocomprende: Since there are non-round manhole covers, the simplest solution must not actually solve the problem every time. And since there are languages in which parentheses are not used around the condition, that solution must not solve the problem every time either. Again, we are capable of engineering multiple solutions to these problems. – Eric Lippert Nov 10 '16 at 14:46
  • 1
    @nocomprende: Also, Einstein never said that. Einstein said It can scarcely be denied that the supreme goal of all theory is to make the irreducible basic elements as simple and as few as possible without having to surrender the adequate representation of a single datum of experience. – Eric Lippert Nov 10 '16 at 14:47
  • @EricLippert nothing works every time. Every engineering decision is a trade-off. Maybe the way that C was designed allowed it to do everything that it needed to without surrendering any 'representations', and made peoples' jobs easier? That is an engineering consideration also. Was the analog TV standard inadequate? It stood for 70 years. The even older FM standard is still going strong. I wonder if any modern computer languages will last as long as C or be as widely used? –  Nov 10 '16 at 14:55
  • @EricLippert My first response may have been cryptic - this is what I was getting at: "Why are many manhole covers round" is not a tautological question; "because they are (members of the set of) round manhole covers" is a tautological reply to it. Rephrasing the question to prefigure the tautological response does not alter this - if it did, we could "answer" many 'why' questions this way. Similarly, there is nothing tautological about Velovix' question, and, as others of shown, there is a non-tautological answer. – sdenham Nov 12 '16 at 13:25
  • @Kos Go's choice in this matter may have been informed by the discovery that, in C-like languages, omitting the braces increases the risk of error. Once you have made the braces mandatory, you no longer need the parentheses. – sdenham Nov 12 '16 at 15:49
  • Mathematica's Wolfram languages uses neither braces, parentheses nor 'then' and ''else', but commas between the conditonal, the 'then' part, and the 'else' part. It can be very easy to overlook the comma that stands for 'else'. – sdenham Nov 12 '16 at 15:53

10 Answers10

157

There needs to be some way of telling where the condition ends and the branch begins. There are many different ways of doing that.

In some languages, there are no conditionals at all, e.g. in Smalltalk, Self, Newspeak, Io, Ioke, Seph, and Fancy. Conditional branching is simply implemented as a normal method like any other method. The method is implemented on booleans objects and gets called on a boolean. That way, the condition is simply the receiver of the method, and the two branches are two arguments, e.g. in Smalltalk:

aBooleanExpression ifTrue: [23] ifFalse: [42].

In case, you are more familiar with Java, this is equivalent to the following:

aBooleanExpression.ifThenElse(() -> 23, () -> 42);

In the Lisp family of languages, the situation is similar: conditionals are just normal functions (actually, macros) and the first argument is the condition, the second and third argument are the branches, so they are just normal function arguments, and there is nothing special needed to delimit them:

(if aBooleanExpression 23 42)

Some languages use keywords as delimiters, e.g. Algol, Ada, BASIC, Pascal, Modula-2, Oberon, Oberon-2, Active Oberon, Component Pascal, Zonnon, Modula-3:

IF aBooleanExpression THEN RETURN 23 ELSE RETURN 42;

In Ruby, you can use either a keyword or an expression separator (semicolon or newline):

if a_boolean_expression then 23 else 42 end

if a_boolean_expression; 23 else 42 end

# non-idiomatic, the minimum amount of whitespace required syntactically
if a_boolean_expression
23 else 42 end

# idiomatic, although only the first newline is required syntactically
if a_boolean_expression
  23
else
  42
end

Go requires the branches to be blocks and doesn't allow expressions or statements, which makes the curly braces mandatory. Therefore, parentheses aren't required, although you can add them if you want; Perl6 and Rust are similar in this regard:

if aBooleanExpression { return 23 } else { return 42 }

Some languages use other non-alphanumeric characters to delimit the condition, e.g. Python:

if aBooleanExpression: return 23
else: return 42

The bottom line is: you need some way of telling where the condition ends and the branch begins. There are many ways of doing so, parentheses are just one of them.

Jörg W Mittag
  • 103,514
  • 8
  • 2
    of course in a language where either bare expressions aren't a statement (e.g. something like older BASIC where a calculated value must be either assigned to a variable or passed to some other statement) or where there are no prefix operators you should always be able to identify the end of an expression and start of a statement anyway. I could definitely see a BASIC variant managing without a delimiter at the end of an IF statement. – Periata Breatta Nov 07 '16 at 16:28
  • 4
    Also, since C was designed in the 70's, and computation was expensive, adding a little parenthesis would probably make the parser a little bit easier to write. – Machado Nov 07 '16 at 17:33
  • 4
    Re: Lisp: "actually, macros". In practice IF is a special form in Scheme and CL (just for completeness). – coredump Nov 07 '16 at 18:09
  • @coredump in Lisp in general, all of the various options for a conditional can be implemented as macros as long as one of them has some special form provided by the runtime, but which one it actually is can vary from Lisp to Lisp. In particular if if is implemented as a macro that wraps the then and else branches in lambdas, the "special" form can easily be a call to a three-argument C (or other native code) FFI function rather than something the compiler has to know about and handle irregularly. – Alex Celeste Nov 07 '16 at 19:14
  • @Leushenko Indeed. My comment is here to help casual readers understand how it is handled in the two main dialects, where IF happens to not be a macro. – coredump Nov 07 '16 at 19:25
  • 1
    @Leushenko: And, e.g. in MISC, which is lazy-by-default, all of the conditional forms are just normal functions, neither macros nor special forms. (Indeed, AFAIR, MISC has zero special forms?) – Jörg W Mittag Nov 07 '16 at 20:11
  • 1
    Although this overview is quite illuminating, it does not answer the question: Why the braces, when there is no apparent syntactical necessity? – Leviathan Nov 08 '16 at 17:01
  • @Leviathan: I thought the very first and very last paragraphs answer that question: because there is a syntactic necessity. – Jörg W Mittag Nov 08 '16 at 21:04
  • 1
    Yes, you claim the necessity, but this clearly doesn't explain the OP's example. Telastyn's answer on the other hand provides a clear explanation. – Leviathan Nov 08 '16 at 22:37
  • Since the question explicitly calls out C, C++ and Java, some discussion of the design considerations in those languages would probably be warranted - e.g. why can't/don't those languages use any of the approaches the languages you mention do? Or to put it more generally, why would a language choose parenthesis versus the other techniques? – R.M. Nov 09 '16 at 19:41
  • Python also has conditional expression like return 23 if aBooleanExpression else 42 – Peter M. - stands for Monica Nov 09 '16 at 22:08
  • Whaaa...? This is so misleading. You can totally have a language where the syntax is just if condition statement;... it's only a problem if the meaning is ambiguous. (If that's what you meant, then you should have mentioned it.) And the main reason it's ambiguous is that C++ allows basically arbitrary expressions to be statements (like +x). Otherwise it might well have worked. – user541686 Nov 10 '16 at 10:21
69

The parenthesis are only unnecessary if you use braces.

if true ++ x;

For example becomes ambiguous without them.

Telastyn
  • 109,398
  • Why would that be the case? It's more ambiguous without the braces. – Robert Harvey Nov 07 '16 at 02:54
  • 1
    With the braces, you know everything from if to the braces is the conditional. – Telastyn Nov 07 '16 at 02:56
  • 1
    Oh, sorry. Got caught up in some of your double-negative logic. Nevertheless, I'm going to have to go ahead and disagree with you here. I've seen a lot of curly-brace code, and never once have I seen this form without the parentheses. If you can find in the spec where it says these are optional... (I'm not going to bother myself; the C language spec is as opaque as all of the other specs I've tried to read.) – Robert Harvey Nov 07 '16 at 03:01
  • 29
    @RobertHarvey - The parenthesis are required by pretty much every language I'm aware of. Certainly C and its kin. The OP is asking why they are required - and it's because the language would become ambiguous otherwise. – Telastyn Nov 07 '16 at 03:05
  • Not necessary in swift, which I don't like if for no other reason than parenthesis make the code more human readable imo. – GRW Nov 07 '16 at 06:42
  • 25
    Just off the top of my head, parenthesis are not required for if in: basic, assembly, python, bash/zsh, tcl, batch, brainfuck, or machine code. Lacking parenthesis only makes an if ambiguous if the language has been designed to depend on them. – candied_orange Nov 07 '16 at 06:42
  • 5
    @CandiedOrange But in BASIC, Python, Bash, etc., the if-condition is terminated by a colon/semicolon/newline. There is always some explicit character sequence that separates the condition from the body. – Nayuki Nov 07 '16 at 07:12
  • 2
    @Nayuki explicit or implicit, that character sequence doesn't have to involve parenthesis. There are plenty of useful unambiguous languages that look nothing like c. – candied_orange Nov 07 '16 at 07:48
  • 12
    Im astonished that nobody mentioned the most logical and readable version - in Pascal (incl. Delphi) it's if Condition then .... – Ulrich Gerhardt Nov 07 '16 at 07:52
  • 18
    Go is a good example of doing the opposite. It makes braces {} compulsory and therefore does not require parens around the expression. Not only is parens not required but if I remember correctly adding parens would cause a compilation error - they're forbidden – slebetman Nov 07 '16 at 09:14
  • How is this example ambigous? I don't see any other way of parsing than if (true) {++x;}? – Eiko Nov 07 '16 at 10:49
  • 2
    @Eiko It's ambiguous in the general case if y ++ x;. In the special case where y is the expression true, one of the two interpretations becomes invalid, making it non-ambiguous. But this special case is recognized at a stage where the expression tree has already been built. – Theodoros Chatzigiannakis Nov 07 '16 at 11:12
  • 1
    @TheodorosChatzigiannakis So you seem to agree that the given example is not ambiguous at all. As it is the only thing in this answer, I think it really should be modified right away. I can see that using variables instead of constants that might give a problem with C/C++. Still, in Java that example won't work, as there's no ++ for boolean, which is mandatory for if-clauses. No question that parentheses or brackets help both human and machine to understand the code - but looking for the "ambiguity-effect" here. – Eiko Nov 07 '16 at 11:51
  • 10
    @Eiko Let me rephrase. The example in the answer is syntactically ambiguous, even though it's semantically unambiguous (as you noted). But since the parsing phase happens before semantic analysis, the parser will encounter the ambiguity -- and it must either make an uninformed guess, or fail. If (for any reason) the parser chooses not to fail, the semantic analyzer will work with the resulting tree, whatever that is. I haven't seen a compiler where the semantic analyzer is willing to ask the parser to reparse the subtree and make a different choice at the syntactically ambiguous construct. – Theodoros Chatzigiannakis Nov 07 '16 at 12:06
  • 2
    @Eiko Given the above, I think the most sensible choice for the parser is to simply fail, on the grounds of this syntactical ambiguity (due to the lack of semantic information at that moment in time). Thus, this would be rejected by the compiler as a whole. And since we generally want languages to be implementable in a sensible fashion, it's probably okay to allow compilers to reject this construct as ambiguous. – Theodoros Chatzigiannakis Nov 07 '16 at 12:08
  • 1
    @TheodorosChatzigiannakis Thanks for pointing out the difference between syntactical and semantical ambiguity. Though the "justification" seems rather technical than conceptual. ;) – Eiko Nov 07 '16 at 12:22
  • 1
    @Eiko Technical, yes, but that is how compilers work! It's useful to understand the basic phases of your compiler, shell, etc., so that you can reason about things like this more easily. – wchargin Nov 07 '16 at 14:09
  • 2
    @slebetman: why would Go forbid parenstheses around the if condition? It doesn't look like it does. Would be a bit strange too because parens are generally understood as no-ops which only affect how expressions are parsed into the AST and nothing else; ((((4)))) should thus be the same as 4. (Of course warning about such unnecessary parens is perfectly sensible. In C and C++ this isn't really possible because at least with the C preprocessor, reliable macros are often only possible if you toss in a few redundant parentheses.) – leftaroundabout Nov 07 '16 at 15:00
  • 1
    The plural of "parenthesis" is "parentheses". Therefore, "parenthesis are" is right out. – Monty Harder Nov 07 '16 at 20:11
  • 1
    @leftaroundabout: Ah, I was mistaken. Go considers it a style issue so it is removed from the code if you run gofmt (which all go projects tend to do). As to why certain things in Go are errors, Go's philosophy is that if something is important enough to merit a warning then it is important enough to be a compile-time error. If not then it's not important enough to be a warning. For things that fall under the broad heading of coding standards, everyone is supposed to run their code through gofmt before committing. – slebetman Nov 08 '16 at 01:34
  • Rust, for example, throws out parentheses but mandates braces. – OJFord Nov 09 '16 at 00:28
  • @Ulrich Gerhardt: While I'm astonished that anyone could think that Pascal is " logical and readable". Tastes differ, of course, but I don't see how that fits any language that requires you to write programs from the bottom up, rather than top down. – jamesqf Nov 09 '16 at 05:52
  • @jamesqf: I was talking about syntax (and with tongue in cheek :-)). Not sure what you mean by bottom up. I can structure my Delphi code quite reasonably. – Ulrich Gerhardt Nov 09 '16 at 05:58
  • Ambiguity can always be handled, e. g. by a precedence rule. I guess one could simply create a version of C which does not require the parentheses around the condition (thus making them optional) and which still creates valid code in all cases. Your example could be interpreted as being equivalent to if (a) ++b or if (a++) b, whatever seems more appropriate. The question of why Dennis Ritchie chose to make the () mandatory is rather a linguistic one. – Alfe Nov 09 '16 at 16:54
  • @CandiedOrange You (and several others) are claiming that disambiguation is not the answer because there are alternative ways of doing it, but their existence does not alter the fact that for the languages Velovix is asking about, parentheses are how it is done. If I get on a plane because I want to go to Chicago, the fact that I could go by train does not mean that I am not on the plane for the purpose of going to Chicago. – sdenham Nov 12 '16 at 13:45
  • @sdenham My reaction was to Telastyn. For a good reaction to Velovix see Fred Larson – candied_orange Nov 12 '16 at 13:54
22

Parentheses in an if statement do not have the same meaning as parentheses used within an arithmetic expression. Parentheses in an arithmetic expression are used to group expressions together. Parentheses in an if statement are used to delimit the boolean expression; that is, to differentiate the boolean expression from the rest of the if statement.

In an if statement, parentheses do not perform a grouping function (though, within the if statement, you can still use parentheses to group arithmetic expressions. The outer set of parentheses then serves to delimit the entire boolean expression). Making them required simplifies the compiler, since the compiler can rely on those parentheses always being there.

Robert Harvey
  • 199,517
  • I don't see how it simplifies the compiler. The rule IF '(' expression ')' statement is no simpler than IF primary_expression statement. Notice that the latter is equally unambiguous. – user58697 Nov 08 '16 at 23:31
  • @user58697: No, only the latter has the ambiguity where a postfix operator on primary_expression cannot be distinguished from a prefix operator on an expression-statement. To copy Telastyn's answer, if true ++ x;. Also, if empty statements exist, if a & f; can be either an empty statement and binary & inside the condition, or a unary & at the start of the statement. But when matching parentheses, there's exactly one match for the opening ( – MSalters Nov 09 '16 at 00:08
  • @MSalters A postfix operator does not parse as a primary. A primary expression is one of IDENTIFIER, CONSTANT, STRING_LITERAL and '(' expression ')'. – user58697 Nov 09 '16 at 02:06
  • @user58697: You seem to have a particular language in mind. And it appears to have a rule that parentheses are not needed if and only if the conditions is an "IDENTIFIER, CONSTANT or STRING_LITERAL". I'm not sure that makes things easier. – MSalters Nov 09 '16 at 08:27
16

As other have already partially pointed out this is due to the fact that expressions are also valid statements, and in the case of a block with just one statement you can drop braces. This means that the following is ambiguous:

if true
    +x;

Because it could be interpreted as:

if (true + x) {}

instead of:

if (true) {+x;}

A number of languages (e.g. Python) allow you to avoid the parenthesis but still have an end-condition marker:

if True: +x

However you are right that we could define a language where the parenthesis are never required: a language where an expression is not a valid statement will not have this problem.

Unfortunately this means that things like:

 ++x;
 functionCall(1,2,3);

would not be valid statements, so you'd have to introduce some weird syntax to be able to perform such actions without creating expressions. A simple way to do this is to simply prepend the expression by a marker like [statement]:

[statement] ++x;
[statement] functionCall(1,2,3);

Now the ambiguity disappears since you'd have to write:

if true
    [statement] ++x;

But as you can see I don't see such a language be widespread since putting the parenthesis around an if-condition (or a : at its end) is much better then putting such a marker for every expression statement.


Note: the use of a [statement] marker is just the simplest syntax I could think of. However you could have two completely distinct syntaxes for expressions and statements with no ambiguity between them which would not require such a marker. The problem is: the language would be extremely weird since to do the same things in an expression or a statement you'd have to use a completely different syntax.

One thing that comes to mind to have two separate syntaxes without such an explicit marker would be, for example: force statements to use unicode symbols (so instead of for you'd use some unicode variation of the letters f, o and r), while expressions to be ASCII only.

Bakuriu
  • 291
  • 2
  • 6
  • 2
    A language actually exists that uses such a expression statement marker: If you want to evaluate an expression for its side effects, you need to explicitly discard its value in Nim. However, that's just done for type safety, not for syntactic reasons. – amon Nov 07 '16 at 10:10
  • @amon Nice, I didn't know about that. Anyway, as I said the marker isn't really needed it's just a simple way to achieve that distinction without inventing unintuitive syntaxes. – Bakuriu Nov 07 '16 at 10:21
  • 1
    @amon - many BASIC variants also have a strict separation between expressions and statements. Expressions are only allowed in places where the value will actually be used (e.g. variable assignments, statements like PRINT that perform an action, and so on). Procedures that aren't used to calculate a value are invoked by a keyword (typically "CALL", although at least one variant I'm aware of uses "PROC") that prefixes their name. And so on. BASIC usually delimits the end of the expression in an IF statement with "THEN", but I can see no technical reason that requirement couldn't be dropped. – Periata Breatta Nov 07 '16 at 16:37
  • 1
    There is a language very popular in the 80s that have blocks without parens, braces, colons or another marker and accept expressions as statements everywhere and some statements act like expressions (compound operators like += and ++). It´s worsrt, there is a dumb pre- processor before compiler (? simbol in example in fact is a function after PP). There is no ;. Sure, it need a marker for continuation line, but this is discouraged. https://harbour.github.io/doc/clc53.html#if-cmd. The compiler is fast and simple (created with Bison/Flex). – Maniero Feb 25 '17 at 18:22
  • @bigown They achieve that by using a separate syntax for logical-conditions, so, basically, the conditions for if, while ecc are limited compared to generic expressions used in other languages. Sure: if you have more than two syntactical categories (like statement, expression, logical-expression, coffee-making-expression, ...) you can trade some freedom. – Bakuriu Feb 25 '17 at 19:44
10

It is common for C-family languages to require these parentheses, but not universal.

One of Perl 6's more noticeable syntactic changes is that they modified the grammar so that you don't have to give the parentheses around if, for and similar statements' conditions. So something like this is perfectly valid in Perl 6:

if $x == 4 {
    ...
}

as is

while $queue.pop {
    ...
}

However, because they're just expressions you can put parentheses around them if you want, in which case they are just ordinary grouping ones instead of a required part of the syntax as they are in C, C#, Java etc.

Rust has similar syntax to Perl 6 in this department:

if x == 4 {
    ...
}

It seems to me like a feature of more modern C-inspired languages is to look at things like this and wonder about removing them.

  • While your answer provides some insight into other languages, it does not answer "Why does this odd syntax exist and why is it so common?" –  Nov 07 '16 at 15:17
  • You're quite correct. I was really looking to add context to the question, which is not something easy to do in this platform. I guess ultimately if I do provide an answer to the question it's "just because, as there's no technical reason the grammar couldn't have accommodated not having them". But that's not a very useful answer. – Matthew Walton Nov 08 '16 at 11:02
  • In Perl 5 there is both. For a normal if or loop constructs with BLOCKs, the parens are required, e.g. in if ( $x == 4 ) { ... } or foreach my $foo ( @bar ) { ... }. When postfix notation is used the parens are optional, as in return unless $foo; or ++$x while s/foo/bar/g;. – simbabque Nov 08 '16 at 12:35
6

There is one aspect which I am surprised that none of the existing answers have brought up.

C, and many C derivatives and look-alikes, has a peculiarity in that the value of an assignment is the assigned value. A consequence of this is that an assignment can be used where a value is expected.

This allows you to write things like

if (x = getValue() == 42) { ... }

or

if (x == y = 47) { ... }

or

unsigned int n = 0 /* given m == SOME_VALUE */;
while (n < m && *p1++ = *p2++) { n++; }

(which is implicitly treated as while (n < m && *p1++ = *p2++ != 0) { n++; } because C treats non-zero as true; incidentally, I think that's just about strncpy() in the C standard library)

or even

if (x = 17);

and it is all valid. Not all syntactically valid combinations are necessarily useful (and modern compilers specifically warn about assignments inside conditionals, because it is a common error), but some of it actually is useful.

Parsing such statements would likely be far more difficult if there was not some unambiguous way to determine where the conditional expression begins and ends.

Parenthesis were already used to delimit function names from function arguments, so I guess they seemed like a natural choice also to delimit keywords from keyword arguments.

Sure, alternative syntaxes could be defined to do the same thing. But doing so would increase complexity, particularly in the parser which would then need to deal with two different sets of syntax for largely the same thing. Back when C was being designed, computing power (both in terms of number-crunching ability, working memory, and storage capacity) were extremely limited; anything that reduced complexity at little or no cost to readability was almost certainly a welcome change.

Using parenthesis might seem slightly archaic today, but it's not like that given someone with some familiarity with the language, it impairs readability compared to some other syntax that is capable of expressing the same things.

user
  • 2,713
5

The reason is mostly history.

At the time that the first C compiler was written, computers have very limited ram, cpu and compilers where written “by hand” with few tools to help compiler writers. Therefore complex rules were costly to implement in a compiler. C++, C#, Java, etc were all designed to be easy for C programmers to learn, hence there was no “unnecessary” changes made.

In ‘c like' languages conditionals (if, while, etc) do not require an explicit block off code, you can just use a simple statement.

if (a == d) doIt()

or you can combine statements together into a compound statement by putting them with in {}

We like the compiler to find error we make and to give as an error message we can understand.

Ian
  • 4,603
3

Java and C++ both were developed after C had become a very popular programming language. One consideration in the design of each of those languages was that it would appeal to C programmers and woo those programmers to use the new language. (I was one of the C programmers they wooed successfully.) C++ additionally was designed to be (almost) interchangeable with C code. In order to support these goals, both C++ and Java adopted much of C's syntax, including the parentheses around the conditions of if, while, and switch statements.

Hence the reason why all these languages require parentheses around the conditions of those statements is because C does, and the question is really just why C requires those parentheses.

The origins of the C language are described in this article by Dennis Ritchie, one of the principal authors of its development (some might even say the principal author of its development). As told in that article, C was originally developed in the early 1970s as a system programming language for computers with extremely limited space in main memory. It was desired to have a language that was higher-level than assembly language, but given the resources available to work with, the ease of parsing the language was also important. Requiring the parentheses would make it relatively easy to identify the conditional code.

One might also infer that the ability to write programs using fewer characters was considered an advantage, and two parentheses take less space than the keyword THEN that was used in FORTRAN and other high-level languages at that time; in fact, since the parentheses could also replace spaces as delimiters of symbols, if(a==b) was four whole characters shorter than IF a==b THEN.

In any event, some balance had to be struck between how easily human beings would be able to read, write, and understand programs written in C, how easily a compiler could parse and compile programs written in C, and how many kilobytes (!) would be required both for the program source and the compiler itself. And parentheses around the conditions of if, while, and switch statements was how people chose to strike that balance in the design of C.

As evidenced in several other answers, once you take away the particular circumstances under which C was developed, all kinds of alternative forms of syntax have been used for the conditionals of various programming languages. So the parentheses really just come down to a design decision that was made by a few people under certain constraints at a certain time in history.

David K
  • 485
  • I'm not sure it's fair to say that C++ was designed the way it was "in order to woo those programmers to use a new language". Remember C with classes? – user Nov 09 '16 at 09:25
  • @MichaelKjörling Admittedly, the Java developers were much more explicit about the "wooing." But note that the linked article cites, as one reason why Stroustrup chose to start with C as the basis of his language, that C was widely used. One way in which this provided a motivation to stay close to C was because existing code could easily be adapted (as I already stated)--but also existing coders could easily adapt. – David K Nov 09 '16 at 14:39
  • @MichaelKjörling I suppose the original wording of my answer suggested that the "wooing" was a greater factor in the language design than it actually was. I've edited the answer to try to clarify that it was merely one thing that factored into the language design. – David K Nov 09 '16 at 14:49
3

Many here reason that without the parentheses the syntax would be ambiguous and imply silently that this would be somehow bad or even an impossible situation.

In fact, languages have lots of ways to deal with ambiguities. Operator precedence is just one instance of this topic.

No, ambiguity isn't the reason for the parentheses. I guess one could simply create a version of C which does not require the parentheses around the condition (thus making them optional) and which still creates valid code in all cases. The example of if a ++ b; could be interpreted as being equivalent to if (a) ++b; or if (a++) b;, whatever seems more appropriate.

The question of why Dennis Ritchie chose to make the () mandatory (and thus coining this meme for lots of derived languages) is rather a linguistic one. I guess the notion of stating clearly that the condition is an expression rather than a command was the father of the thought.

And in fact, C was designed to be a parseable using a one-pass parser. Using a syntax with mandatory parentheses around the condition supports this aspect.

Alfe
  • 241
  • I see a downvote on my answer. Please be so kind to explain in a comment what you didn't like about it. Maybe I can improve it then. – Alfe Nov 10 '16 at 08:52
  • In a Swift-like language “if x ++ y” would be illegal because a unary operator must be attached to what it opersted on. Either “if x++ y” or “if x ++y”. Binary operator must have space on both sides, or on neither side so “if x ++ y” or “if x++y” would be both binary operators. – gnasher729 Oct 24 '23 at 20:07
0

Parentheses around if conditions are not required in Fortran, Cobol, PL/1, Algol, Algo-68, Pascal, Modula, XPL, PL/M, MPL, ... or any other language that has a then keyword. then serves to delimit the condition from the following statement.

The closing parenthesis in C etc. functions as then, and the opening one is formally redundant.

Above remarks apply to traditionally-parsed languages.