Hacker News new | ask | show | jobs
by jonahx 2745 days ago
Contemptuous scorn seems to be the officially-sanctioned strategy for responding to reasoned critique or even questions about "the go way" within the community.

My favorite example here is this arrogant dismissal of the idea that a one line expression, rather than a 5 line mutating statement, might be preferred for conditionally setting a value:

    if expr {
        n = trueVal
    } else {
        n = falseVal
    }
> The if-else form, although longer, is unquestionably clearer. A language needs only one conditional control flow construct. [0]

...

   n = expr ? trueVal : falseVal
"Unquestionably"

[0] https://golang.org/doc/faq#Does_Go_have_a_ternary_form

5 comments

What I find particularly off-putting is that this attitude of superiority is sometimes married with objective incorrectness. If you're going to claim something is black and white, it should actually be black and white.

&&, ||, switch, select, for, and while all do conditional execution in Go.

So the rule is not "A language needs only one conditional control flow construct." The rule is really, "We didn't think a conditional operator was worth it." That's a fine rule, but it's better to be honest about it than to pretend the language was designed around some pure principle that doesn't actually exist.

Yeah, I agree about it being off-putting. There's very little science in programming language ergonomics, so it all comes down to taste, right?

However, I wonder how much of this is a difference in substance and how much is about writing style? There is an older, authoritive style that has an implicit "in our opinion, of course" and sounds pretty grating these days.

I remember being taught in school to remove "I think" and qualifiers expressing uncertainty, under the theory that in an opinion piece, that's understood.

Especially these days when hyperbole is common, I prefer writers that have a humble writing style, but also try not to get hung up on stylistic differences.

The authors of Go have stated they themselves sometimes miss the ternary form, but have seen it abused too much (deeply nested ternary).

This isn't an insult to programmers, it is an option that clarity of code is more important then continence. Thus all if and for statements also require {} brackets.

This would be a reasonable position:

"While the ternary is often clearer, we chose to sacrifice expressiveness and brevity for the sake of preventing abuses, which we found were all too common."

But that is not the claim being made in the FAQ.

> Thus all if and for statements also require {} brackets.

Indeed this rule seems to spring from the same philosophy. It is most certainly not a preference for clarity, though. It is a preference for consistency.

The philosophy is: "We're giving up expressiveness and brevity because in our experience most people can't be trusted to not shoot themselves in the foot."

This choice would be much more palatable if they were honest about it. But instead, they take the road of insisting that the verbose consistency is actually clearer, which it isn't, at least in many people's opinions.

> It is most certainly not a preference for clarity, though. It is a preference for consistency.

FTR, with "most certainly" you're committing the same fault your accusing the Go team here. You might not think it matters for clarity. I, at least, disagree.

> in our experience most people can't be trusted to not shoot themselves in the foot.

I don't understand the difference between this suggested phrasing and talking about clarity. I'd argue you tend to shoot yourself in the foot if and only if you aren't clear about what you're doing. Clarity and lack of footguns seem directly correlated.

> FTR, with "most certainly" you're committing the same fault your accusing the Go team here.

Fair enough. It's too late to edit.

> I don't understand the difference between this suggested phrasing and talking about clarity. I'd argue you tend to shoot yourself in the foot if and only if you aren't clear about what you're doing.

This is partially true but it's not that simple imo.

In my OP, the ternary version is clearer. But if you allow it, then you also open the door to nested ternaries, and foot shooting.

Allowing single line if statements (as, eg, ruby does) also allows for clearer code, at the expense of consistency.

> Allowing single line if statements (as, eg, ruby does) also allows for clearer code, at the expense of consistency.

This (or rather allowing conditionals without braces) was what I was referring to. They are a foot-gun, because of the lack of clarity. It's a common source of bugs in C/C++ code that a developer thought they'd add a line of code to a conditional block or loop but didn't, because of a lack of braces. Requiring braces unconditionally make it always unambiguous and obvious what block a given statement belongs to.

Obviously YMMV - this is, as most discussions in programming, a matter of opinion. Which was my point :)

I'm aware of the reasoning. As you say, in C people would carelessly edit:

    if (condition)
      doSomething
to

    if (condition)
      doSomething
      doSomething2
So fair enough, you protect against that. You cannot therefore conclude that:

    if (condition) {
      doSomething
    }
is clearer or that 1 line if statements aren't clear. First of all, you've purchased your insurance at the cost of brevity. Which is quite a high price, especially when you have to use them constantly to write:

    if err != nil {
      return err
    }
and when it forces all of your 1 line conditional expressions to be 4 - 6 lines, per my OP.

And there are solutions that allow you to buy your insurance without such a high price. You can invert the position of the if, as ruby does. You could make a rule that when you don't have braces you have to write your statement on the same line. The point is this isn't the only way out. And clarity is not the same as preventing one specific kind of error, which occurs only in a context which could be changed as well.

In 10 years the expression form will be added to Go. It will be hailed as great progress, as adding clarity, and as unquestionably the Go way.
Oh man don't tell me these things. I haven't used Go yet in production, but the more I learn about the ways it diverges from functional programming, the more I doubt I'll ever use it.

I was thinking I could write my own if(condition, true_case, false_case) method similar to the way it's done in spreadsheets, but Go also doesn't have macros or inline if/else expressions, so there is simply no way to emulate ternary logic in a performant manner :-(

Oh let's be very clear: Go is actively, explicitly anti-FP, anti-expressiveness, anti-brevity. Those are simply not its values. And any attempts to write Go in FP style will be considered unidiomatic Go.

And the missing ternary will be the least of your problems. Do you enjoy `map` and `filter`? Sorry, the "go way" is to use a for loop every time. Reimplementing map on every type where you need it is considered best practice in Go. Have a problem with that? Expect a snarky comment about your priorities.

This can all be pretty frustrating when you've experienced the joys of more expressive languages.

Go has good concurrency primitives and is fast. That's what it's good at. Those are the reasons to use it. Temper your expectations accordingly.

> Have a problem with that? Expect a snarky comment about your priorities.

Whereas your comment is completely devoid of snark.

That comment, however, is a comment on hacker news.

Not the official docs of a programming language. In one of those, a bit of snark is really quite normal and of no real impact.

Why not have if/else be an expression in the first place, like Kotlin?

  n = if(expr) trueVal else falseVal
No need to learn a separate ternary operator.
Quite a few languages do if expressions, and IMO they’re great. Simple syntax, readable and powerful. It’s crazy to me that any new language wouldn’t have them.
The argument specified in the docs is "a language needs only one conditional flow construct" (in a language, of course, that has half a dozen conditional flow constructs ...)

The more palatable argument that people who try to cover for ... seems to be that when people nest if expressions, it becomes a mess. I'm glad these people exist.

The real reason is found here: http://dtrace.org/blogs/wesolows/2014/12/29/golang-is-trash/

(or if you prefer, in the compiler's source itself. It doesn't take a compiler expert to realize it's not very clean code. Even violates the go style, and the C one before that was just horrendous)

The TLDR is that Go's compiler is a "fisher-price my first compiler" and really shows that the authors simply barely knew how to get a compiler working in the first place. That they were not ready to go into a rational discussion on programming language and type theory ... is not something anyone should be surprised about.

That they avoid the arguments by dismissing the people making them in such a condescending way is ... well, there's not really anything good to say about that.

Ken Thompson has been writing compilers for over 50 years now. If you believe that Ken "barely knew how to get a compiler working in the first place", we have nothing to talk about, as you obviously made up your mind already.
Then read the source for the compiler yourself. Tell me I'm wrong.
Not only I have read it, I have written several compiler targets for it. You are wrong. It's by far the easiest compiler I have worked with.
Because the designers of Kotlin are more open to experimentation and new ideas.

  (setq n (cond
    (expr trueVal)
    (t falseVal)))
This particular idea dates back to at least 1965.
Er, yes, I should say “new ideas about which features are worth stealing from Lisp” :)
> A language needs only one conditional control flow construct.

If by "one" you mean `if` _and_ `switch` then yes!

and `select`