Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: Go 2: add a ternary conditional operator #33171

Closed
phrounz opened this issue Jul 18, 2019 · 77 comments
Closed

proposal: Go 2: add a ternary conditional operator #33171

phrounz opened this issue Jul 18, 2019 · 77 comments

Comments

@phrounz
Copy link

@phrounz phrounz commented Jul 18, 2019

I disagree with the Go convention and language's designers arguments here https://golang.org/doc/faq#Does_Go_have_a_ternary_form and think that it is a real missing feature in the language.

Consider in C the following code:

printf("my friend%s", (nbFriends>1?"s":""));

or in C++ :

std::cout << "my friend" << (nbFriends>1?"s":"") << std::endl;

In Go it causes either huges repetitions which can cause mistakes, or very verbose and inefficient code, or both, for something which should be straightforward:

Solution 1:

// horribly repetitive, risk of divergence between the two strings
if nbFriends > 1 { 
  fmt.Printf("my friends\n") 
} else { 
  fmt.Printf("my friend\n")
}

Solution 2:

// difficult to read
fmt.Printf("my friend")
if nbFriends > 1 { fmt.Printf("s") }
fmt.Printf("\n")

Solution 3:

// difficult to read
var plural = ""
if nbFriends > 1 { plural = "s" }
fmt.Printf("my friend%s\n", plural)

Solution 4:

// dangerous (ifTrue and ifFalse are both evaluated, 
// contrary to a real ternary operator), 
// and not generic at all (works only for strings)
func ifStr(condition bool, ifTrue string, ifFalse string) string {
  if condition { 
    return ifTrue
  }
  return ifFalse
}
fmt.Printf("my friend%s\n", ifStr(nbFriends > 1, "s", ""))

Solution 5:

// horrible to read, probably inefficient
fmt.Printf("my friend%s\n",
		func(condition bool) string {
			if condition {
				return "s"
			}
			return ""
		}(nbFriends > 1))
@bcmills bcmills changed the title Add a ternary form [Suggested labels: Go2 LanguageChange proposal] proposal: Add a ternary form Jul 18, 2019
@gopherbot gopherbot added this to the Proposal milestone Jul 18, 2019
@gopherbot gopherbot added the Proposal label Jul 18, 2019
@bcmills bcmills added Go2 and removed Proposal Go2 labels Jul 18, 2019
@bcmills
Copy link
Member

@bcmills bcmills commented Jul 18, 2019

@gopherbot, add label Go2, LanguageChange

@ianlancetaylor ianlancetaylor changed the title proposal: Add a ternary form proposal: Go 2: add a ternary conditional operator Jul 18, 2019
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jul 18, 2019

See also #31659 and #32860.

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jul 18, 2019

This decision has already been enshrined in a FAQ, as you note. If you want to argue that the FAQ answer should be changed, you need more than a few examples. I promise you that we've seen and considered those examples already. What you need is data: real programs with code that would become simpler and easier to read by adding a conditional operator. You also need arguments against the common concerns about the conditional operator, such as that it makes code harder to read especially when nested.

Also, a minor point, but your example is not great since it only works for English, and does not support localization of message strings.

@alanfo
Copy link

@alanfo alanfo commented Jul 18, 2019

@ianlancetaylor

In #31659 you made what I thought was a very good counter-suggestion of having a built-in cond function to provide ternary functionality. This needed to be a built-in (as opposed to a generic function) to enable short-circuiting evaluation of the true/false arguments. It still suffered from the possibility that people could nest cond functions though personally I didn't regard that as a fatal problem because, even if they did, it should still be more readable than the hieroglyphics of C's ternary operator itself.

As that proposal has now been closed, do you intend to pursue that suggestion further or have you given up on the idea of having an alternative ternary form altogether?

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jul 18, 2019

I don't personally intend to push that idea further. That was more of a discussion thought than a serious suggestion. Of course, I don't mind if someone wants to polish it into a real proposal. But in order to be accepted I think we would still need to see some data as to how much it would simplify real existing programs.

@alanfo
Copy link

@alanfo alanfo commented Jul 18, 2019

OK, thanks for clarifying.

One has only to look at code in other C family languages to see how common the ternary operator is but it would be difficult to analyze Go code itself since, as @phrounz pointed out in his opening post, a number of constructions are used to work around its absence.

Using the cond idea, his example would become:

fmt.Printf("my friend%s\n", cond(nbFriends > 1, "s", ""))

Having said all that, if we get generics, I'd personally be content to write my own cond function and, given the lack of short-circuiting, only use it where the arguments were cheap to evaluate.

@DongchengWang
Copy link

@DongchengWang DongchengWang commented Jul 20, 2019

In my opinion, to write more code (just a few lines) is better than to figure out the rule of x ? a : b. The if statement may seems verbose (not sure) but easy to understand.

Besides, a ternary conditional operator can be easily abused when people write multiple nested x ? a : b. The benefit of introducing it isn't great enough.

@Marcial1234
Copy link

@Marcial1234 Marcial1234 commented Jul 20, 2019

I see ternary operators only being easy to visualize in one-liners functions. Even then, most of the time they deal with error handling, at which case is better to adhere to a "the less indentation the better" approach by having the error or least probable path for a function be wrapped in an if and handled then, as opposed to having multiple branching logic.

@tero-dev
Copy link

@tero-dev tero-dev commented Jul 20, 2019

I think the example is kind of a bad one considering its only about one character and is not really readable in my opinion (?:"s":"")
but i do agree that the ternary operator should be added its a no-brainer for me
and i made up some examples which would be useful for me personally and i think you can somewhat relate to some of them.

const PORT = production ? 80 : 8080
instead of

const PORT = -1
if production {
    PORT = 80
else {
    PORT = 8080
}

fmt.Printf("Running %s build!", production ? "Production" : "Debug") .. etc

But of course the ternary operator is very hard to learn.

@alanfo
Copy link

@alanfo alanfo commented Jul 20, 2019

Yes, that's a good example particularly if it's at top-level:

const production = true

//...

const PORT = production ? 80 : 8080

as you don't then need an init function to initialize PORT.

A built-in cond function might be able to be used as a const initializer though a generic version definitely could not.

@DisposaBoy
Copy link

@DisposaBoy DisposaBoy commented Jul 20, 2019

@Terottaja @alanfo

I think the idiomatic solution to that specific problem is to use Build Constraints.

@DisposaBoy
Copy link

@DisposaBoy DisposaBoy commented Jul 20, 2019

@Terottaja

See my other comment for the solution for global variables/constants.

For local variables/constants, I think the idiomatic way to write this peace of code:

const PORT = -1
if production {
	PORT = 80
else {
	PORT = 8080
}

is:

PORT := 8080
if production {
	PORT = 80
}

You could argue that I changed the const to a var, but I'd be surprised if the compiler wasn't smart enough ™ figure out that PORT is constant so IMO it makes no difference in real code.

@alanfo
Copy link

@alanfo alanfo commented Jul 20, 2019

Although it probably wouldn't matter in this particular example whether PORT was a const or a var, more generally it might matter. For example, if you were declaring some integer which was to be used to define the size of an array.

Perhaps I should make my own position clear on this proposal. Whilst I personally have no problem with the 'standard' ternary operator, I'm not sure it would be a good idea to introduce it into Go in that form. I'd much prefer a cond built-in instead which is far more readable though, realistically, I see little chance of either being adopted.

@tero-dev
Copy link

@tero-dev tero-dev commented Jul 21, 2019

@Terottaja

See my other comment for the solution for global variables/constants.

For local variables/constants, I think the idiomatic way to write this peace of code:

const PORT = -1
if production {
	PORT = 80
else {
	PORT = 8080
}

is:

PORT := 8080
if production {
	PORT = 80
}

You could argue that I changed the const to a var, but I'd be surprised if the compiler wasn't smart enough ™ figure out that PORT is constant so IMO it makes no difference in real code.

im just talking about if you have a lot of this kind of stuff in your code the ternary operator definitely would be more clean in this case, just my opinion

@tero-dev
Copy link

@tero-dev tero-dev commented Jul 21, 2019

In my opinion, to write more code (just a few lines) is better than to figure out the rule of x ? a : b. The if statement may seems verbose (not sure) but easy to understand.

Besides, a ternary conditional operator can be easily abused when people write multiple nested x ? a : b. The benefit of introducing it isn't great enough.

there will always be people abusing it, code can be abused its inevitable but will that be affecting you? in most cases, no

@Lexkane
Copy link

@Lexkane Lexkane commented Jul 28, 2019

I support this feature, while it can lead to abuses in code, it is really beneficial to compiler optimisations, when u avoid generic if /else and replace it with ternary operator.
People have been doing bitwise shifts from the start (who can blame them, and still no one suggests let's take away bitwise shifts cause of readability), and ternary operator is just crucial to have nowdays.

@randall77
Copy link
Contributor

@randall77 randall77 commented Jul 28, 2019

@Lexkane: The compiler already has optimizations that use conditional moves. We don't need a language construct to force such optimizations. For instance, the following code uses one:

func f(x, y int) int {
	r := 3
	if x < y {
		r = 7
	}
	return r
}

If you have particular instances where a conditional move is not being generated, and you think it should, open an issue with the code.

@DmitriyVTitov
Copy link

@DmitriyVTitov DmitriyVTitov commented Aug 22, 2019

Since I use Go and Javascript in my job at the same time it has been countless times I wanted to write x ? a : b in Go programs! I should have written it down to show all theese cases to @ianlancetaylor ! It all was real programs.
Ternary operator is the one we all learn at school (not even at University) so in it's classic form it is the natural way to write and read code.
We all learned that there are three types of operators: unary, binary and ternary. Go lacks one type for no real reason IMO.
Both hands fo x ? a : b.

@DeedleFake
Copy link

@DeedleFake DeedleFake commented Aug 22, 2019

We all learned that there are three types of operators: unary, binary and ternary. Go lacks one type for no real reason IMO.

There's no reason that there has to be, though. 'ternary' is just an English word that means 'composed of four parts'. You could just as easily have quaternary or quinary operators, too.

Personally, I feel that ternary operators default to being annoying to read. With unary and binary operators, you can easily see exactly where everything is, but with ternary it's not always clear what goes with what, especially once you start nesting them. I can see the argument for them being cleaner in specific situations, but outside of those situations they're almost always worse. gofmt could help, potentially, but only if it was a lot more aggressive about how it reformatted code than it is. Maybe some kind of limited one could be introduced, like disallowing nesting or chaining it, but at that point I'm not sure if it's really worth it.

@DmitriyVTitov
Copy link

@DmitriyVTitov DmitriyVTitov commented Aug 22, 2019

It has been already said that one can make the mess with the simplest set of operators. It's true that Go-code is simpler to read and write than Java or Javascript code. But it's not impossible to make it unreadable.
So ternary operator is for one-liners mostly and should be used for those cases.
Otherwise you can take "if - then - else", nest it several times and make your code a total mess. It's always up to you.
I think that people underestimate the frequency one-liner expressions are arise in the code. Sometimes they are rare but sometimes they fill half of the code written and in later case i want to have ternary operator preferably in the form it is in Javascript.

@lukechampine
Copy link
Contributor

@lukechampine lukechampine commented Aug 22, 2019

I like that in Go, control flow is generally done with statements, not expressions (function invocation being the obvious exception). Many popular languages strive for "everything is an expression," which is often fun, but imo encourages writing "clever" code. Go, to me, is all about minimizing cleverness.

By the way, another (gross) way to implement a ternary expression is:

map[bool]string{true: "", false: "s"}[nbFriends == 1]
@seebs
Copy link
Contributor

@seebs seebs commented Aug 29, 2019

What are you talking about? i++ is perfectly allowable as a statement in Go. what's not allowed is using it in an expression, where it is evaluated both for a value and for a side effect.

https://play.golang.org/p/m_LbSbmT1Ar

As someone reasonably solidly familiar with C, I nonetheless find that I'm fine without the ternary operator, and I like the resulting code better. I've stopped using it as much in C, too, just like I've become more consistent about using braces on all blocks, not just blocks with more than one statement in them.

@nkev
Copy link

@nkev nkev commented Aug 29, 2019

I didn't mean i++ on it's own, I meant as an expression like fmt.Printf("%d", i++) which would be a convenience for some of us.

@seebs
Copy link
Contributor

@seebs seebs commented Aug 29, 2019

Yes, it's definitely convenient, but it is, pretty clearly, less maintainable. People make mistakes with it, people misunderstand code using it. It is a source of bugs, and it just plain doesn't add that much value.

Yes, if I want to do x++, I have to do it as its own statment before or after the Printf. That is indeed a cost, at all. But in exchange, I get:

  • I don't suddenly have x getting the wrong values if I comment out some of the Printf calls.
  • Changes to the format messages don't break my program logic.
  • Someone else skimming the code (or me without enough coffee) won't just plain miss that the increment is in there.

It is a tradeoff, but I think it's a pretty good one. I spend some of my time trying to answer newbie programming questions, because that's part of how we develop healthier language communities. I spend a lot less time trying to puzzle through subtleties in punctuation in people's Go code than I do in their C code, and they have a lot fewer problems caused entirely by subtle typos.

I assure you, this isn't purism coming from people who don't understand or appreciate C. It's a considered decision that this language seems to get a lot of value from simply not being that complicated, and that leaves us more room to be doing complicated things with our logic since we're not spending so much of our effort parsing the code.

@nkev
Copy link

@nkev nkev commented Aug 29, 2019

I hear you, but I'm not convinced on all of that. For example, the following works in Go and according to your argument, it should be the only allowed syntax:

	for i:=0; i<5; i=i+1 {
	  fmt.Printf("%d\n", i)
	}

But the more popular/familiar syntax IS also allowed:

	for i:=0; i<5; i++ {
	  fmt.Printf("%d\n", i)
	}

Why do you think that is?

@seebs
Copy link
Contributor

@seebs seebs commented Aug 29, 2019

My argument does not in fact state that only the first should be allowed. I like the second better, it's simpler and easier to read, because the increment operator is a standalone thing, not a side-effect.

Note that you can't do:

i := 0
for i++ < 5 {
    ...
}

Because Go doesn't let you put assignments, or increments, in expressions. And that may be an inconvenience sometimes, but the frequency with which it does not result in people misunderstanding an expression and not realizing it modifies values is basically 100%, which is nice.

@nkev
Copy link

@nkev nkev commented Aug 29, 2019

See that's too purist to me :) Anyway, my point is, since both i=i+1 and i++ are allowed in loops, I say also allow a ternary variation for those who prefer the single-line convenience, e.g.

Port := production ? 80 : 8080

as well as the usual:

Port := 8080
if production {
	Port = 80
}

If it's about simplicity, I think the former is simpler.

@seebs
Copy link
Contributor

@seebs seebs commented Aug 29, 2019

What about:

Port := production++

or

fmt.Printf("port: %d\n", production++)

Both of those are also shorter using the C idiom than they would be in Go. But I would argue that in both cases, the possibility of that complexity existing makes the entire program slightly harder to understand -- you now have to be watching out for those effects all the time.

At a more fundamental philosophical level: The problem is that your solution is not only for those who prefer that "convenience". It's also imposed by force on everyone else, forever. Because everyone has to read other people's code. So people can't opt-out of a feature like this. They can't say "well, that's harder for me to maintain, so I won't use it" and not have to deal with it. They're stuck with it being part of their world. Whenever they read code that anyone else could have worked on, they have to watch out for a new set of complexities.

In practice, this "simplicity" comes at a significant cost, because it's not actually simplicity, it's just making the expression shorter. It's like the single-line braceless if; it seems like it's simpler, but then you need a second line and there's a non-zero chance that you forget to add the braces then, and pretty soon you've lost more time than you would have just putting the braces there.

I know what happens if you write:

Port := production ? 80 : 8080

A few days later:

Port := production ? 80 : test ? 4080 : 8080

But then someone realizes that the two bools are a bad choice, and fixes that:

Port := mode == "production" ? 80 : mode == "test" ? 4080 : 8080

and because it was just one line, and using ?:, people feel like making it longer is Extra Effort, and they don't fix it or clean it up. And now they've got an investment in it being that way.

And that's how you end up with ?: operations nested 15 deep, which I've seen in actual code, which should absolutely have been lookup tables.

@phrounz
Copy link
Author

@phrounz phrounz commented Aug 29, 2019

And that's how you end up with ?: operations nested 15 deep, which I've seen in actual code, which should absolutely have been lookup tables.

"if-else" operations nested 15 deep, should also absolutely have been lookup tables, though.

@seebs
Copy link
Contributor

@seebs seebs commented Aug 29, 2019

Oh, certainly.

But if you have 15-deep nested if/else operations, and you convert to a lookup table, you don't feel like you've lost the "simplicity" of the single-line solution.

@nkev
Copy link

@nkev nkev commented Aug 30, 2019

The problem is that your solution is not only for those who prefer that "convenience". It's also imposed by force on everyone else, forever

I couldn't disagree more because the truth is the opposite! It is actually your purist view that imposes your way of doing it and limits my freedom to choose a short-hand version. If you don't want to use it, that's your choice, but don't limit my choice!

If I can choose to write a shortened a := "freedom" instead of var a string = "freedom" then I should have the freedom and convenience of a ternary assignment.

Go tooling does a great job of standardising code formatting and I think that alone makes it quite easy to read other people's code.

The bottom line for me is, I find ternary assignments easier to read and understand because they are more naturally translated to English. I believe this is why it is so popular in many other languages. To me this:

port := production ? 80 : 8080

...translates to : "Is this production? if yes, port is 80 and if no, port is 8080"
(a simple, straight forward single assignment, even when nested)

port := 8080
if production {
	port = 80
}

This translates to: "port is 8080 (period) Oh, but if this is production, change port to 80" (second assignment).

The second is definitely NOT easier to read for me. Never has been.

If it's the ? and : that is bothering people, I'd also be happy with any alternative single line syntax.

@networkimprov
Copy link

@networkimprov networkimprov commented Sep 3, 2019

This single-line construct works for non-computed initial values. A way to extend this to computed initial values would be great.

v := a; if t { v = b }        // non-computed initial value

v := f(); else if t { v = b } // f() not evaluated where t==true

Sadly go fmt destroys many useful single-line constructs. I don't use go fmt for that reason; telescoping readable compact code makes it less readable. But that's tangential.

@seaskyways
Copy link

@seaskyways seaskyways commented Sep 14, 2019

This functionality is achievable without a ternary operator if Go 2 adds Generics

func ternary(type T)(cond bool, vTrue, vFalse T) T { 
    if cond { return vTrue } else { return vFalse }
}

Of course using this wouldn't be pretty especially if there was more than one ternary call.

As for evaluation, this may be an optimization on the compiler level.

@phrounz
Copy link
Author

@phrounz phrounz commented Sep 15, 2019

This functionality is achievable without a ternary operator if Go 2 adds Generics

func ternary(type T)(cond bool, vTrue, vFalse T) T { 
    if cond { return vTrue } else { return vFalse }
}

Of course using this wouldn't be pretty especially if there was more than one ternary call.

As for evaluation, this may be an optimization on the compiler level.

Hum no, vTrue and vFalse will always be evaluated, I mean

ternary(3>2, func1(), func2())

will cause the call of both func1() and func2(). No compiler could know that func2() do not need to be evaluated... and it should never assume that anyway, because it's a fundamental principle that in a function call the arguments are always expected to be evaluated, before the call of the function itself. If func2() does stuff additionally to returning a value, we want this stuff done, otherwise it would be very unpredictable and difficult to comprehend.

(Contrary to a real ternary operator where the value of false is not supposed to be evaluated by principle.)

@seaskyways
Copy link

@seaskyways seaskyways commented Sep 16, 2019

This functionality is achievable without a ternary operator if Go 2 adds Generics

func ternary(type T)(cond bool, vTrue, vFalse T) T { 
    if cond { return vTrue } else { return vFalse }
}

Of course using this wouldn't be pretty especially if there was more than one ternary call.
As for evaluation, this may be an optimization on the compiler level.

Hum no, vTrue and vFalse will always be evaluated, I mean

ternary(3>2, func1(), func2())

will cause the call of both func1() and func2(). No compiler could know that func2() do not need to be evaluated... and it should never assume that anyway, because it's a fundamental principle that in a function call the arguments are always expected to be evaluated, before the call of the function itself. If func2() does stuff additionally to returning a value, we want this stuff done, otherwise it would be very unpredictable and difficult to comprehend.

(Contrary to a real ternary operator where the value of false is not supposed to be evaluated by principle.)

Then the signature would be like so:

func ternary(type T)(cond bool, vTrueFunc, vFalseFunc func() T) T { 
    if cond { return vTrueFunc() } else { return vFalseFunc() }
}

I gotta admit though, this implementation is a whole lot ugly :(

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Oct 1, 2019

There were additional comments since we declared this a likely decline (#33171 (comment)), but as far as we can tell none of them said anything substantially new. We agree that there are cases where the ?: syntax would be convenient, but overall it doesn't seem worth adding to the language.

-- for @golang/proposal-review

@nkev
Copy link

@nkev nkev commented Oct 1, 2019

So the decision is based on "doesn't seem worth adding"?
I'm not surprised at at all... Ternary expressions would destroy the "purity" of the language, right?

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Oct 2, 2019

Language changes are always a cost-benefit tradeoff. There is rarely an unambiguous answer.

@obinoob

This comment was marked as off-topic.

@dash-
Copy link

@dash- dash- commented Mar 7, 2020

On its surface, the refusal to implement this basic feature is analogous to arguing that bicycles can be dangerous if they're fast, and refusing to make a bike with high gears as a result. Some may get mixed up in the conversation about whether Go's language architects are right or wrong, but I'd prefer to go up a level of abstraction and consider whether languages should couple feature concerns with maintainability concerns:

If feature X could be abused and result in a rats nest of code, is that sufficient reason for feature X to be excluded from the language?

I would argue it may be, but not by itself: It should be weighed against Demand and Difficulty. If a feature is high in demand and easy to implement, it would be better to decouple the concerns by implementing the feature and presenting a way to disallow it -- and even disallow it by default.

In fact, if the demand is high enough, even difficulty is a bad reason to refuse it. Consider the class syntax in Javascript (ES2015): The language's architects really didn't want to add the feature, and it was actually quite a bit of work to add the syntax, but demand was incredibly high. What did they do? They added the syntax, knowing full well that any organization that did not want the feature could easily disallow the syntax at the linting level.

This is the appropriate resolution for the ternary operator, given the demand. De-coupling these concerns is appropriate, and solving them in a more configurable way would make the most sense. The same should happen for things like "unused variable" errors that make linting concerns into "stop-the-presses you need to fix this one thing before the program will run" crises. (Yes, I know there's a _ solution, but it's still just the case that this should be configurable)

It is a mistake to think that a language should be the product of a small number of architects that know better without a deep connection to those that are actually using the language. The call for data to prove the architects of the language wrong is admirable, but such analysis is unnecessary. Just look at the size of this thread: There is demand.

Unfortunately, ignoring demand is what leads to competing products: In this case, this is how languages get forked. Do you want to get forked? (To be clear: This is a prediction, not a threat.
I'm definitely not forking a language.)

@griesemer
Copy link
Contributor

@griesemer griesemer commented Mar 7, 2020

@Dash This issue is closed, and I am not going to argue it, but I'd like to correct what I believe is a misrepresentation. You're implying that Go is a language that is "... the product of a small number of architects that know better without a deep connection to those that are actually using the language." This is certainly not true. Everybody in the Go Team, and certainly the "architects" are writing Go code every day, and have been writing a substantial amount of it ever since 2007. We also interacting with other Go users on an almost daily basis. We absolutely have a deep connection with those that actually use the language, which is us - among many others.

@seebs
Copy link
Contributor

@seebs seebs commented Mar 7, 2020

I'm not one of the architects, and I use the language heavily, and I regularly encounter situations where I would almost certainly use a ternary operator if it were available. And then I read my code later, and I think about it, and I'm glad it's not there. YMMV.

I don't think that making things like this, or the unused variable warnings, "configurable" would make my life as a developer easier; I think it'd make my life as a developer harder.

@nkev
Copy link

@nkev nkev commented Mar 7, 2020

I'm not one of the architects either, and I use the language heavily too, and I regularly encounter situations where I would almost certainly use a ternary operator if it were available. And then I read my code later, and I curse the few people who deny us this useful feature!

@phrounz
Copy link
Author

@phrounz phrounz commented Mar 7, 2020

Same here, I use Go everyday and would need it everyday and I am convinced it would make my code clearer and even more robust.

By the way, in the proposal of "Reword FAQ answer"

using ternary operator instead of conditional statement (not expression) for brevity;

"Brevity" is mentioned like if it is a bad thing. Brevity helps readability. The whole idea of a readable code is that it is "straight to the point" of what it actually does. Not like affecting 8080 or -1 to the port, and then 80 later in the code because this is production.

@alanfo
Copy link

@alanfo alanfo commented Mar 7, 2020

I think there's little chance now of Go getting a ternary operator, not just because the Go team have consistently argued against it but because (judging by the emoji voting) around 60% of the community are against it as well.

However, if Go does eventually get generics, I think the team should seriously consider adding a ternary function to the standard library notwithstanding that there'll be no short-circuiting except possibly by way of compiler optimization.

If they don't do this, then the 40% who are in favor of some sort of termary operator/function (myself included) will immediately write their own. This will create a readability and maintenance nightmare because different names will be chosen (Cond, Iff, Iif, Pick, Choose, Tern etc.) and they'll be in packages with different names.

If it's added to the standard library instead, then this fragmentation won't occur as everybody in favor will use the standard version and those who don't like it will at least know what it does.

@ArnoldoR
Copy link

@ArnoldoR ArnoldoR commented Apr 7, 2020

func ifThen(condition bool, ifTrue,ifelse interface{}) interface{}{
if condition {
return ifTrue
} else {
return ifelse
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.