Live data from Hacker News

Is This a Branch?

bartwronski.com

41–50 of 78 posts

Re: Is This a Branch?

#41
post #28

Earlier quoted context omitted.

I have been reading HN for a long time but your comment is the first time I violently felt the need to create an account and respond. I want you to consider how significant that is. Ternaries are NEVER easier to read.

They are clear when succint, and especially for setting a value. -- example: var x; if(this) x = 10; else x = 11; -- is uglier than: var x = this ? 10 : 11;

[deleted]

Re: Is This a Branch?

#42
As usual, the programmer should look at the generated assembly, when reasoning about performance. Sometimes compilers are smart, optimizing away things people wouldn't imagine they can, and sometimes they are really dumb, pessimizing code in unimaginable ways (to the extent that just deleting code from the output, which doesn't naturally correspond to anything in the source code, makes the output better). Relying on the compiler to perform magic without verifying the results is an antirational stance. Personally, I'd prefer if optimizations were applied based on what's visible in the source code, instead of the wild-west that we have now. E.g. inline function calls based on annotations left by the programmer, not because you (the compiler) feel like it.

The Rust compiler can be very good at optimizing iterator pipelines, however a while ago I wrote a function which didn't have any branches whatsoever in it, but the generated assembly was ridden with them. What could have been 5 instructions consisting of simple bit operations (everything done in registers, not loading anything from memory), ended up as 12 (? IIRC) ridden with conditional jumps. No matter how I changed the source code, which operations I used, the output was the same. Getting to the desired result shouldn't be stifled by the compiler having a mind of its own, making its own decisions. A sane default could be set, but some annotations to have a greater control over the result would be appreciated.

Optimizing compilers also make debugging harder. Making the the output and the source code closer together would help making sense of a debugging session.

Re: Is This a Branch?

#43
post #3

Ifs are generally bad for readability though, because they force the reader to understand your control flow. Replacing an if with a ternary makes it more readable, not because the generated code is any different, but because a reader immediately knows that they don't need to scan through the two sides for control flow constructs (because the two sides of the ternary are guaranteed to be expressions rather than blocks…

I have been reading HN for a long time but your comment is the first time I violently felt the need to create an account and respond. I want you to consider how significant that is. Ternaries are NEVER easier to read.

I am impressed that account name has gone unused, until now. :D

Re: Is This a Branch?

#44
post #3

Ifs are generally bad for readability though, because they force the reader to understand your control flow. Replacing an if with a ternary makes it more readable, not because the generated code is any different, but because a reader immediately knows that they don't need to scan through the two sides for control flow constructs (because the two sides of the ternary are guaranteed to be expressions rather than blocks…

Sorry, perhaps I don't understand how ternary operators are any different than if; then; else. In fact for readability I very much prefer guard statements that don't include an else at all.

if/else can contain arbitrary control flow (return, break, throw, goto) in the bodies, so you have to read the whole body to know what's going on. Ternaries are just expressions so however complex the body is, you know it's always just going to evaluate to a value.

Re: Is This a Branch?

#45

Earlier quoted context omitted.

I have been reading HN for a long time but your comment is the first time I violently felt the need to create an account and respond. I want you to consider how significant that is. Ternaries are NEVER easier to read.

We can't objectively say whether they're easier to read or not. Opinions differ. We can objectively say that ternaries are shorter and simpler however. (Simpler because they can do fewer things than an if-statement or if-expression.)

I don’t think that’s the case in gcc. https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html: “A compound statement enclosed in parentheses may appear as an expression in GNU C“

So, you can do (untested)

foo = bar ? ({a=1;b=2;}) : ({a=2;b=1;});

That’s widely supported in other compilers for compatibility reasons (https://stackoverflow.com/questions/6440021/compiler-support...)

You can also (mis)use the comma operator like this (again untested):

  foo = bar ? f(),g() : g(),f();
but that is more limited.

Re: Is This a Branch?

#46
post #42

As usual, the programmer should look at the generated assembly, when reasoning about performance. Sometimes compilers are smart, optimizing away things people wouldn't imagine they can, and sometimes they are really dumb, pessimizing code in unimaginable ways (to the extent that just deleting code from the output, which doesn't naturally correspond to anything in the source code, makes the output better). Relying on…

This is one things I like so much about SBCL, it not only compiles the Lisp code directly to native code, with the disassemble function you can print out the generated code for each function to see how much the compiler was able to optimize a function. This is especially important in the context of dynamic languages to see where generic operators have to be called and where the type inferencer was able to compile it into an assembly instruction like integer multiplication.

Re: Is This a Branch?

#47
post #42

As usual, the programmer should look at the generated assembly, when reasoning about performance. Sometimes compilers are smart, optimizing away things people wouldn't imagine they can, and sometimes they are really dumb, pessimizing code in unimaginable ways (to the extent that just deleting code from the output, which doesn't naturally correspond to anything in the source code, makes the output better). Relying on…

This sounds tempting, but it would trigger a wave of unreadable, irrelevant micro optimization by many programmers.

If you have a desired assembly result, write it yourself in the first place.

The one concession to this I would like is a "constant time" marker for cryptography functions where it is an absolutely critical property that there be no data dependant branches.

(This is a little different on GPUs where branches are so unreasonably expensive, and it sounds like that would also benefit from "no branches here" markers. The downside of this is that it makes valid code un compilable if the compiler can't find a branchless way of doing it.)

Re: Is This a Branch?

#48
post #40

Earlier quoted context omitted.

When I find a place where a complex ternary is probably the best choice, I'm a big fan of the following format, because I find it clear that each line is a new condition myvar = condition_1 ? value_1 : condition_2 ? value_2 : condition_3 ? value_3 : value_fallback;

> where a complex ternary is probably the best choice Under what circumstances would that happen? I've never encountered a nested ternary that wouldn't be better replaced with readable code, so now I'm wondering what experiences I've been missing. :)

Readability is in the eye of the beholder.

Re: Is This a Branch?

#49

Lots of code has apparent branches which compilers effectively optimize. An easy example is integer signbit: int isignbit(int x) { return x which is reliably optimized to logical right shift. Are there any code patterns where the compiler emits branches that are not apparent in the code? Notwithstanding overflow checks, etc.

That's a good point, but a bad example since 'x cc.

Re: Is This a Branch?

#50

Earlier quoted context omitted.

I have been reading HN for a long time but your comment is the first time I violently felt the need to create an account and respond. I want you to consider how significant that is. Ternaries are NEVER easier to read.

I don't want to come of as insensitive, it sounds like you've had some really bad experiences with ternaries in the past and it's important to acknowledge your experience. But I just want to say that not all ternaries are like that. In a more serious tone, ternaries in places where they should be used, i.e. as expressions, are in my opinion much clearer to read than replacing them with an if-else statement. In my min…

> In my mind, an if/else block is an imperative entity that describes two different actions that could happen. Even if in reality both branches are trivial, my mind will be unnecessarily occupied with the fact that it needs to reason about code here, not just data

That's true in some languages. But in some languages if-else can also be used as in expression. e.g. in Rust I can write:

    let foo = if condition { "FOO" } else { "BAR" }
Post reply on HN