7 ms·
Making braces optional in single-statement if/else/while/for clauses is one of the biggest anti-features in C. It's frustrating that it was ported forward to m
by strommen 11y ago
Making braces optional in single-statement if/else/while/for clauses is one of the biggest anti-features in C. It's frustrating that it was ported forward to more modern languages like Java, JavaScript, C#, etc.
I'm glad Python (with semantic whitespace) and Go (with gofmt) solve this problem.
- deweerdt 11y agoI think that gofmt is particularly innovative, in the sense that it acknowledges that formatting is integral part of the language. In the sense that a programming language is not only made to be parsed by a computer, but also read back by a human.
- nathanielc 11y agoYes, and that the nuances of how things are formatted are really not that important, but rather having a standard which provides a consistent reading experience is the important aspect.
- asadjb 11y agoI agree completely with this. After fighting over code formatting for so long (often starting those fights myself), I have thankfully come to realize that what format you use almost never matters, only that you use some standardized format.
- nathanielc 11y agoAnd in the case of go that standard is language wide, not just project, team, or company wide.
- seiji 11y agoExcept the go standard is awful, so a language-wide formatting requirement with bad defaults makes the language basically unusable (since programs are made to be read, not run).
- ansible 11y agoI think that's one of the best contributions golang has made to the programming world. The idea that the language itself should be easy and unambiguous for the compiler and the human to parse. And that a single formatting standard makes life easier for everyone. If we ever move beyond using text files for storing code, we could eliminate formatting differences entirely... but efforts in that direction have run into many issues in the past.
- aikah 11y ago> I think that gofmt is particularly innovative, in the sense that it acknowledges that formatting is integral part of the language. gofmt is still optional. Python significant white spaces are not.
- MereInterest 11y agoI thought that the go compiler would throw an error of your code is not in the format produced by gofmt. You don't need to use the tool, but you need to have your code in the same format that the tool would produce.
- neilc 11y ago> I thought that the go compiler would throw an error of your code is not in the format produced by gofmt. This is not the case.
- infogulch 11y agoNope. The gofmt-contract is a purely social one. But it's one held by nearly the entire go community which probably gave you that impression for good reason.
- MereInterest 11y agoWow, true. The first thing that I read was how to set up emacs to run gofmt every time you save a src file. After that, I never questioned it.
- ma2rten 11y agoActually for C there has always been GNU indent, which serves a similar function as gofmt.
- Coding_Cat 11y agoRust does something similar. It doesn't allow for brace-less clauses and it also bitches and moans at you about 'miss-using' camelCase, snake_case, etc. Which is great because it means that by default all project will follow a similar mark-up.
- steveklabnik 11y agoWe also have 'rustfmt' in development, which goes even further than the built-in lints.
- keeperofdakeys 11y agoIn Rust, code like this simply won't compile http://is.gd/e6mBlG http://is.gd/e6mBlG
- kbenson 11y agoWell, yeah, but that's not a huge advantage of Rust. In any language where that's not an allowed construct (and there's quite a few), it won't compile. It won't compile in Perl either (It fails at the compilation stage, not at runtime).
- pavlov 11y agoSingle-line ifs are pretty useful with traditional-style C libraries that expect all checks to be done at call site: if (ptr) call_oldschool_thingy(ptr);
- mediocrejoker 11y agoI'm not sure that expanding your statement to multiple lines is any less "useful". I suppose in certain cases it can make code much more verbose, as one line effectively becomes 3-4, which can make it harder to navigate.
- pavlov 11y agoFairly often there's a whole sequence of this type of calls. For example cleanup of multiple objects: if (image) foo_release(image); if (label) foo_release(label); if (data) foo_buffer_destroy(data); if (window) foo_window_destroy(window); It's easier to see that all objects are being cleaned up when each occupies just one line, as that typically matches the look of the initialization: window = foo_window_create(); data = foo_buffer_create(1, 2, 3); label = foo_label_create(window); image = foo_image_create(window);
- dcvuob 11y agoThose if statement should be written using the ternary operator. In my subjective opinion, putting the expression in the same line as the if statement is awful. Objectively it is worse because you create a possibility of certain types of errors, like a hanging statement or similar. Ternary operator doesn't have those. The second example is missing error checking. So the real code isn't that nice. My point is that C shouldn't look like Python. Small amount of functionality should be written unambiguously and take a lot of space if necessary. Because of the nature of C, it needs a lot boilerplate, and will take a lot of screen space anyway, but that is not a problem, as we are not coding on paper.
- TorKlingberg 11y agoHow would you use the ternary operator there? Like this? image ? foo_release(image) : 0;
- ktRolster 11y ago>I'm glad Python (with semantic whitespace)... solve this problem. Python solved it....then added the problem of making things you can't even see semantically significant. If you write Python, it's helpful to have an editor that makes the difference between tabs and spaces visible....
- MattConfluence 11y agoSince Python 3 the interpreter will halt when detecting mixed whitespace, forcing the programmer to deal with it. https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces
- deleted 11y ago[deleted]
- heinrich5991 11y agoThis is only a problem in Python 2.
- Redoubts 11y ago> it's helpful to have an editor that makes the difference between tabs and spaces visible.... I do this for any and every language. Mixing tabs and spaces always sucks.
- ajross 11y ago> one of the biggest anti-features in C Please. I'm as big a C apologist as you'll find and even I can think of six or nine thing objectively worse about the language. This issue is merely a great bike shed because it allows all of us rabble to join in on a discussion about "compiler" technology. Look: it's a good warning. People should clearly use it. It probably should have been written long ago, and probably would have if our editors hadn't been enforcing this since time immemorial.
- to3m 11y agoAnd now we've got the warning, we can go back to leaving the braces out more often ;)
- strommen 11y agoGood point, there's plenty of bad stuff about C. But optional braces are perhaps the most pointless anti-feature in C. The only benefit is a minor (and subjective) improvement in aesthetics.
- ajross 11y agoYour point being that... aesthetics in a technology (a "programming language") whose whole existence derives from making computer programs easier to write, read and reason about is... unimportant?
- derefr 11y agoThere's probably a word that the parent was looking for; it wasn't quite aesthetics, at least as you've defined it. Sometimes you can write code that looks "prettier", at the expensive of the ability to read and reason about it. Optional braces are frequently used for this effect. Yes, optional braces allow you to fit more code on the screen with less noise—and therefore could be thought to enhance some kind of readability. But at the same time, they require you to think harder about the grouping of the code around them. Unless you've got a reformatting linter, you could have code like this: if(foo) bar; baz; quux; and optional braces require an extra subroutine to be constantly running in your head, looking for those mis-arranged `baz`es that will get executed anyway. That cognitive load detracts from your ability to read and reason about the code. (What'd be really interesting, in my opinion, would be to make C's braceless blocks, and only braceless blocks, have semantic-whitespace. Then the above would be able to be easily reasoned through: `baz` is part of the conditional, because it's on the same line. But this breaks a lot of rather old and inflexible assumptions about how C is parsed, that macro-writers et al depend on.)
- ilek 11y agoI don't find something like the below frustrating really if (a) ... else ... But for some reason I find the below _very_ frustrating. It feels misleading and I find it to be very, very ugly. if (a) ... else { /* Multi line block */ }
- delecti 11y agoI've actually never seen anyone do either of those. I've seen if (a) thing; but never with an else, and certainly never with an else that has a multi-line block. That's definitely somethign I'd call out in a CR.
- ilek 11y agoI call it out in CRs when I see it and I've been fixing any of these I come across in code at work. I'd rather a compiler forces me to put braces around everything than let people have the opportunity to do something like the latter from my original comment.
- Cyph0n 11y agoWhy is that an issue? You would use something like that extensively in Go or JS for example, where you need to perform a check on the returned (Go) or passed (JS callback) error value. The else is executed if there is no error, in my style at least, so naturally it will contain more logic.
- ilek 11y agoI just have a problem with the mixing of braces on an if/else chain I guess. I don't know how to explain it clearly, it just rubs me the wrong way?
- moron4hire 11y agoI agree. I've trained myself to religiously apply curly braces to all blocks, but it'd be more reassuring to know there was a compiler check for it. I do have linters set up to check for it, but I just wish it were default. This is also one of the reasons I like Racket: there's no such thing as ambiguous block delimitation. Also, everything-is-an-expression is very useful.
- pklausler 11y agoHaskell's solution to this problem is also excellent and needs to be better known and copied into newer languages. The language has curly braces around the bodies of 'let', 'case', 'where', and 'do' constructs, and also the bodies of modules, and semicolons between the constituents of those constructs -- but when the compiler demands a '{' and doesn't see one, it uses indentation to insert them in the obvious places. If your indentation is incorrect, you're likely to get an implicit ';' or '}' put in the wrong place, and you go fix it. The scheme works so well that people will often go months into their Haskell education before they encounter code with explicit braces and semicolons.
- wyager 11y agoI've actually never seen production code with braces or semicolons. The only place it's semi-common is when people write complicated expressions and need to put them on one line for the REPL (GHCi).
- arnsholt 11y agoI think another use-case for non-layout version is generated code. If you happen to generate Haskell code, it's easier to keep the syntax correct with the explicit notation rather than the implicit whitespace version.
- GTP 11y agoI don't like Python forcing you to use a particular identation. And in my opinion optional braces are not an anti-feature, "with great powers come great responsibilities": like any other tool it's up to who is using it to use it in the right way.
- abjorn 11y agoI would disagree that optional braces are a "great power." I feel like it's a really nothing feature.
- ygjb-dupe 11y ago> like any other tool it's up to who is using it to use it in the right way. And mandatory seat belt use is foolish, bike helmets are for wimps, and blade guards on saws are a waste of space and money. Just use those tools responsibly :P
- wdr1 11y ago> Making braces optional in single-statement if/else/while/for clauses is one of the biggest anti-features in C. What's frustrating is that K&R still has a lot of example code like that as well. It would be wonderful to see a 3rd edition even if it do nothing but change its code to use braces.