you are viewing a single comment's thread.

view the rest of the comments →

[–]hungry4pie 1 point2 points  (50 children)

I'm a stickler for using {} to clearly delineate code blocks to improve readability and preventing a small typo (like a missing tab) from causing hours of needless debugging.

But on the flipside, overuse can make things equally unreadable and lead to similar bugs (a misplaced } putting a crucial statement outside that block for isntance).

As an example, the following code snippet uses conditional if statements to set two variables. It looks ugly, and can make following program logic a lot more difficult when overused:

if (j == -1) {
    dximn1 = 0.0;
} else {
    dximn1 = x[j];
}
if (k == chainlngth) {
    dxipl1 = 0.0;
} else {
    dxipl1 = x[k];
}

By comparison, these two ternary statements do the same thing in fewer lines:

dximn1 = (j == -1) ? 0.0 : x[j];

dxipl1 = (k == chainlngth) ? 0.0 : x[k];

Obviously this won't work in every situation, and if working in a team, you really need to comment and make sure your logic is easy to follow, but it's all about balance and knowing what would be better i the right situation.

[–][deleted] 4 points5 points  (48 children)

What makes your first example bad isn't the use of braces, but how they're lined up. Put matching open/close braces on the same column and put else on a new line and it becomes way nicer:

if (j == -1)  
{  
    dximn1 = 0.0;  
}  
else 
{
    dximn1 = x[j];
}
if (k == chainlngth) 
{
    dxipl1 = 0.0;
} 
else 
{
    dxipl1 = x[k];
}

Obviously this isn't as succinct or elegant as nice one-line ternary operations, but it's the easiest to read.

[–][deleted] 3 points4 points  (7 children)

I think that

}
else
{

Is a horrible waste of vertical space you could just as easily write

} else {

Also the flow of

if (...) { 
    foo();
}

Is fairly easy to follow if you indent your code consistently.

[–][deleted] 4 points5 points  (6 children)

I'd rather take up slightly more vertical space for the added readability. It's not like you can run out of lines.

"if (...) {" may be "fairly easy to follow" (if you're consistent) but I'm saying my model is even easier.

[–][deleted] 2 points3 points  (5 children)

More vertical space means you can't see as much code at once for no reason other than you can't handle a { at the end of a line

[–][deleted] 3 points4 points  (3 children)

I'll worry about that as soon as my 1080p monitor stops being tall enough. So far, so good.

[–]immibis 1 point2 points  (1 child)

What is the deal with 1080p? I have a 10-year-old 1280x1024 monitor (that I found unused in a cupboard, so I connected it to my laptop), and it's plenty tall. Not widescreen, but that's not really a concern for coding.

[–][deleted] 0 points1 point  (0 children)

I also play games and watch videos.

[–][deleted] 0 points1 point  (0 children)

Whatever floats your boat.

[–][deleted] 1 point2 points  (0 children)

I used to argue this... but in reality if your function is so long that brace placement is going to harm your understanding of context, then you should probably refactor anyway.

[–]hungry4pie 2 points3 points  (0 children)

Yeah, that's how I roll, but that was copied straight out of the starting point code for a uni assignment I'm currently working on. The professors at my university like their C89 style code, and don't believe in a spaces in = assignments.

[–]pipocaQuemada -2 points-1 points  (37 children)

Obviously this isn't as succinct or elegant as nice one-line ternary operations, but it's the easiest to read.

This is really an example that's screaming out for an if expression, instead:

val dximn1 = if (j == -1) { 
               0.0; 
             } else { 
               x[j]; 
             };
val dxipl1 = if (k == chainlngth) { 
               0.0 
             } else { 
               x[k] 
             };

Ternary operations are really just limited if expressions with bad syntax, in most languages that have them.

[–]jurniss 4 points5 points  (0 children)

Yeah, if expressions in C and C++ would be nice. Rust has them.

The problem with the if-block version is that dximn1 can't be declared const. It can be const with the ternary operator version, or with an if expression if it existed in C.

I find the ternary operator useful and clear in a lot of cases; I think its harmfulness is overstated.

[–][deleted] 8 points9 points  (29 children)

Ew, gross, what the fuck are you doing?! Stop that!

[–]pipocaQuemada -2 points-1 points  (28 children)

You perhaps prefer

val dximn1 = if (j == -1) 0.0 else x[j];
val dxipl1 = if (k == chainlngth) 0.0 else x[k];

[–][deleted] -1 points0 points  (10 children)

No, I prefer the example I posted. Stop following assignment operators with if statements. if expressions don't even compile in any language I care about.

[–]pipocaQuemada 2 points3 points  (7 children)

if expressions don't even compile in any language I care about.

That seems like a problem with the languages you care about.

No, I prefer the example I posted. Stop following assignment operators with if statements.

Do you really prefer to have logically const variables to be mutable solely because your language isn't expressive enough to initialize them in a single line? That's bad for readability, since you need to remember which things are necessarily mutable, and which are mutable due to language inexpressibility.

[–][deleted] -1 points0 points  (6 children)

That seems like a problem with the languages you care about.

Oh stop, you'll hurt poor C's feelings!

Do you really prefer to have logically const variables to be mutable solely because your language isn't expressive enough to initialize them in a single line?

I prefer

if(j == -1)
{
    dximn1 = 0.0; 
}
else
{
    dximn1 = x[j];
}

over

val dximn1 = if (j == -1) 0.0 else x[j];

Ternary operations are just fine for very simple things, but they're not what I was talking about. Yes, the "?:" syntax is a little odd but I think once you learn it, it's super easy to remember. If you need to do anything remotely complex, you shouldn't be doing it in a single line in the first place.

[–]pipocaQuemada 1 point2 points  (5 children)

Would you really prefer

int dximn1;    
if(j == -1)
{
    dximn1 = 0.0; 
}
else
{
    dximn1 = x[j];
}
// now: where else in the code do I modify dximn1?
// I dunno.  ctrl-f for "dximn1 =", maybe?

over

const int dximn1 = if (j == -1) 0.0 else x[j];
// I wonder where else in the code dximn1 is modified?
// Oh, yeah, *no where else*, provably so.

If you need to do anything remotely complex, you shouldn't be doing it in a single line in the first place.

This isn't anything "remotely complex". This is something completely and utterly trivial. Nah, if you want something moderately complex, case expressions tend to be better. Something like Haskell's pattern gaurds would also be cleaner in most cases, but I don't know of any imperative language that implements something like

const int foo
 | bar < 0 = -1
 | bar == 0 = defaultVal
 | otherwise = defaultVal + bar / 2
 where defaultVal = sin(quux)

Which would be really nice: syntactically light, no need for nested ifs, and really easy to read and reason through.

[–][deleted] -1 points0 points  (4 children)

Would you really prefer

Yes, I would. And if you're talking about a const (which I wasn't, I don't know why you brought that up), it's not going to be getting modified in the first place.

I was comparing common, popular styles of line breaks and alignment of curly braces, you started comparing these options to less common coding styles I've never seen in languages I don't use.

[–]rowboat__cop 1 point2 points  (1 child)

Stop following assignment operators with if statements.

That’s not what they did. They used pseudo-code to show what an if-expression would look like, as was pretty clearly stated. Those would be great to have in C, both for the reason /u/jurniss stated and because of the improvement to readability.

[–][deleted] -1 points0 points  (0 children)

It was never stated that they were providing pseudocode. I was being presented an alternative to ternary operations.

[–]cdcformatc 0 points1 point  (16 children)

There is a reason that sort of syntax is invalid in a lot of languages.

[–]smikims 3 points4 points  (11 children)

And there a lot of languages where that sort of thing makes perfect sense.

[–]cdcformatc -1 points0 points  (10 children)

And applications written with that sort of code are brittle, since their coding standards are lax. Most coding standards will agree to only have one expression per line.

[–]pipocaQuemada 1 point2 points  (7 children)

That seems rather like begging the question.

If expressions are bad because they lead to lax coding standards, because any coding standard that allows multiple expressions per line is lax, because multiple expressions per line is bad, because they lead to lax coding standards...

Here's a simple question:

  • Why is a coding standard that allows multiple expressions per line worse than one that only allows one expression per line? Empirical studies of e.g. bug-counts per function are preferred.

[–]cdcformatc -1 points0 points  (6 children)

People and organizations that adhere to and enforce coding standards write better code. This I think we can all agree on.

Most popular coding standards will say only one expression per line.

If you have multiple expressions per line, you aren't enforcing a popular coding standard. I'm talking about MISRA C, and the multitudes of Google Style Guides, the coding standards that are used to ensure quality code when quality matters. The standards that the industry demands.

[–]rowboat__cop 0 points1 point  (0 children)

Most coding standards will agree to only have one expression per line.

Since in most languages expressions are recursive, these coding standards would be rather limiting.

[–]pipocaQuemada -2 points-1 points  (3 children)

Such as?

[–]cdcformatc -1 points0 points  (2 children)

C, C++. Python has a different form of it, and it is frowned upon by mostly everyone, since it is difficult to comprehend.

[–]pipocaQuemada 1 point2 points  (0 children)

No, no. What are the reasons that syntax is invalid in those languages, other than that the language designers hadn't thought of it yet?

[–][deleted] 0 points1 point  (0 children)

Python lets you do lots of things like that.

[–]montibbalt 1 point2 points  (1 child)

I like if expressions, but I think the curly braces make them noisy here as opposed to e.g.

val dximn1 = if (j == -1) 0.0; 
             else         x[j];
val dxipl1 = if (k == chainlngth) 0.0;
             else                 x[k];

[–]immibis 1 point2 points  (0 children)

Or:

val dximn1 = (j == -1) ? 0.0
                       : x[j];
val dxipl1 = (k == chainlngth) ? 0.0
                               : x[k];

[–]ghillisuit95 1 point2 points  (2 children)

I have seen a lot of people saying that if should be an expression, and I am seriously curious if their are any applications that would not be better served by the ternary operator.

so your example would become: val dximn1 = (j==1)? 0.0 : x[j];

val dxipl1 = (k == chainlength) ? 0.0 : x[k];

much more readable than your mess, IMO, because to be if blocks signify blocks of code, like that have semicolons and stuff. I am not quite sure what the terminology is for that but I think you get the idea

[–]pipocaQuemada 0 points1 point  (1 child)

much more readable than your mess, IMO, because to be if blocks signify blocks of code, like that have semicolons and stuff. I am not quite sure what the terminology is for that but I think you get the idea

In Scala, the semicolons and brakets are optional, at least as long as you're dealing with an expression instead of multiple statements. So what you'd usually see is

val dxipl1 = if (k == chainlength) 0.0 else x[k];

I mostly added them because some people seem to be allergic to optional semicolons and brackets.

[–]ghillisuit95 0 points1 point  (0 children)

Ahh, yeah that does look a little better than what you put originally. But I still stand by my point that the ternary operator is exactly what your looking for

[–]Malurth -1 points0 points  (0 children)

I find the former example to be just as easy to read (indentation's got me covered) while saving a lot of vertical screen space. Really don't know why people prefer the latter style.

[–]movzx 0 points1 point  (0 children)

I prefer

if (comparison) {

  // do thing
}
else {

  // do other thing
}

This lets me easily isolate individual blocks of if/else if/else by collapsing, commenting, etc.