Hacker News new | ask | show | jobs
by nemothekid 1465 days ago
>There’s no ternary (?:) operator. Every C-like language has had this, and I miss it every day that I program in Go. The language is removing functional idioms right when everyone is agreeing that these are useful.

And everyone agreed so hard that it was removed from almost every modern C replacement (Rust, Nim, Zig, Elixir, Kotlin).

6 comments

Rust has if/else (ternary) and match (N-ary) expressions, so it doesn't need a separate ternary operator. All of the other “C replacements” listed (which are a weird list for that description, especially Elixir, but whatever) have at least if/else-expressions, which, again, are ternaries.
Yeah if I can have decent pattern matching I can live without some other syntax sugars.
Have you met my friend.. erlang ?
Indeed, big fan, though it's rare I get to use it.
True. In Kotlin you can go

    val foo = if (bar) "this" else "that"
and you don't need two separate assignments.
For comparison, in Go it would be:

    foo := func() string {
        if bar { return "this" }
        return "that"
    }()
Bit of an odd use of an anonymous function IMO. Normally I'd write that as:

  foo := "that"
  if bar {
      foo = "that"
  }
Unless the assignment of "foo" is expensive, then you'd assign it in an else.

If you really want to, you can do it in a single line too:

  foo := map[bool]string{true: "this", false: "that"}[bar]
These are rather nasty workarounds, to be honest. Instantiating a map out of the blue is clever, but not very readable (not to mention potential performance concerns eg. if it's code executing in a large loop), and something I'd definitely call out in code review. Note that computing "this" and "that" could by itself be costly, and one of these values is guaranteeed to get discarded.
I've used the map thing a few times, but sparingly. Mostly for things like setting something based on the value of a boolean commandline flag and the like where the performance impact doesn't matter and keeping it on one line offsets the "ugliness" of the construct. You should indeed avoid it for most other things.
I was simply giving an example of only using a single assignment, as the parent stated:

> and you don't need two separate assignments.

Although I do use it far more often nowadays than a decade ago. I've even mentioned it before https://news.ycombinator.com/item?id=30384835.

> And everyone agreed so hard that it was removed from almost every modern C replacement

They removed it because they made the regular "if" statement into an expression, so the separate "ternary" operator expression is superfluous. Rust et al made the "if" situation better than C; Go made it worse.

This is entirely off topic, but how are Elixir or Kotlin "modern C replacements"? Elixir is built off of Erlang and has influences from Ruby and Clojure, and Kotlin is a replacement for Java.

Rust, Nim, Zig, and Go are all fair game in that list, as far as I know being a C replacement is in the mission statement for the creation of all those languages.

I literally don’t understand why so many people believe Go is a C replacement. Like it is by all means in the first camp of managed languages with a huge runtime.
Replacement for C in many areas it is used for != replacement for C in all areas it is used for
Sure, as long as Node, C#, Java, Haskell are all C replacements as well. Which I am okay with claiming, as GC has no considerable overhead for most use cases, but go is not unique in any way or shape.
Go is much closer to C than Node, Java, or Haskell. (I won't make claims about C#, I don't know it well enough -- but I doubt it's as similar to C as Go is.)
All those languages have if-expressions, which is all ?: is.
Totally. In fact, if expressions are the very first example of “if” in the Zig manual

https://ziglang.org/documentation/master/#if

Also, Zig is so into expressions over statements that they plan to remove “function definition as statement”, which I think is awesome. In other words, conceptually function definition is a compile-time expression that creates the function.

Edit: here’s that Zig rfc:

https://github.com/ziglang/zig/issues/1717#

Ternary syntax was statement-oriented languages' compromise to get one bit of nontrivial expression syntax into the language. In Rust everything is already an expression, including if-else, so additional syntax isn't necessary.
Elixir has the if-else being an expression.

foo = if x, do: 1, else: 2