Ternary operator


#125

This would remove the only advantage the ternary operator has, the fact that people know it from java. In that case you can just use if else.


#126

It still saves 4 characters. :grin:


#127

Pls don’t start this discussion again. I am pretty sure everything has been said about the “but it saves x characters” argument on both sides. So as long as there is not a new one there is no reason to get into it again


#128

In the spirit of making code more readable to everyone, I propose replacing the { } with begin and end keywords as in good old languages like Pascal.

For those confused by ternary operator, I have a question. How do you see generics and extension functions? I’m arogantly guessing that coroutines are definitely a source of confusion stress.


#129

I’m not sure if you really mean this, but even if begin and end where more readable and I am not sure about this, a change like this would break backwards compatibility.

Every language has some necessary constructs which are complex and hard to understand at first. But they are necessary. There is no way you can make coroutines more understandable. The ternary operator on the other hand would be unnecessary as there is an already existing concept which leads to the same result.


#130

Maybe the begin and end can be addedy but not replaced as of breaking channges :joy:

And for me the coroutines are indeed a source of confusion stress.
About the confusion, I think at myself that it indeed is clear what the ternary operator does.
(you do almost the same with nullable if it is null : ?: else: ?.)

(text == null)?     first()   : second()
text          ?.let{first()} ?: second() 

or shorthand:

(text == null)?: second()
text          ?: second() 

(witch is obviously not possible)

I however think there can be beter use-cases for the colon:

  • Making it an oprator fun for creating a range that can go both up and down
  • The equivalent of to for a mapEntry, such that the forEach with receiver now can refer to key and value instead of first and second

And in kotlin, I always will associate the questionmark with nullable and I hope it stays that way.


#131

Kotlin does not need ternary. Initially I wanted to vote for adding it. But now I think that this

    llMain.visibility = if (b) VISIBLE else GONE

looks better that this

  llMain.visibility = b ? VISIBLE : GONE

#132

Even as an option this would be breaking, because I am 100% sure there are people out there (me included) who have functions named begin and end :stuck_out_tongue:

And srsly “Coroutines are confusing” is not an argument for the ternary operator. Yes they might be, but there is no better option. For the ternary operator there is an option and I would argue a better one.


#133

I made a summary of the whole topic and the arguments (named once or over and over).
But before the discussion, its important to know what is possible:

(success) ? first() : second()  //possible
(success) ?: second () // not possible as it checks if success is null

Next, I didn’t want to chain facts between opinions, as it makes the opinions look like facts.
I couldn’t however distinguish all the facts from opinions, so I could have made some facts opinions and vice versa.
The opionions are cursive.
Next, I tried to be unopinionated, but I’m against the ternary operator. This can be reflected below.

  • A lot of languages have it which:
    - makes the conversion from those languages harder
    - means that the construction should be unlearned by those programmers.
  • It looks less verbose
  • Its shorter
    • but its at most 6 chars shorter
    • being short is not a goal of kotlin
  • The choice should be left upon the programmers
    • but more concepts for the same thing is harder to learn.

cons:

  • for (at least) beginning programmers: it is hard to learn.
  • Its not a priority (at the moment) so the attention can be focussed on more important things
  • The questionmark in Kotlin is associated with null:
    - the shorthand if/else ?: is not even possible.
    - the code can be interpreted different:
    success? foo : bar can be interpreted as if(success == null) foo else bar
  • It’s not needed as:
    • If is already an expression
    • you can create a comparable function yourself
      infix fun <T : Any> Boolean.t(value: T) : T? = if(this) value else null
      (I however recommend you not to use this)

When something is not on the list, please respond. Otherwise, we just keep repeating ourselves.


#134

Sorry to take so long to get back to you. You completely ignored my distinction between groups 2, 3, and 4 which all fall into your group about being “teached” a C like language. I didn’t contradict the assertion that many are taught a C-like language and estimated the figure at 90%. But just because they learned Java or similar language does not mean that ternary operator is easier to read to them.

There is plenty of other evidence. As I have said the fact that ternary operator is used so infrequently in Java code even though it actually has a reason to exist in Java is one piece of evidence. Googling and seeing how many peope say don’t use it because it is harder to read is also good evidence.


#135

I, for one, emphatically throw my hat into the ring in favor of the standard C-style ternary operator. While I’m not averse to shaving away questionably or unnecessary functionality that does not make sense in the new language (such as old for-style loops), this is just change for the sake of change. It’s no less ugly than the traditional method, it’s bulkier making it harder to cleanly fit on a single line, but also lopsided in a way that doesn’t lend well to splitting up over multiple lines (at least for that there are when statements). And it’s honestly rather confusing in an extremely subtle way that would, if anything, only trip up beginner programmers.

Someone who doesn’t know what a ternary operator is will see “x = a ? b : c” and think “I don’t know what this is, I should look it up.” They see x = if( a) b else c they might say the same thing or they might say “What is this, some sort of predicate? Is x a value or a command path? I know what an if-else block is, is this a standard if else block? What does assigning that even do? Can I do that with other control structures?”

The fact that even IntelliJ IDEA has problems formatting the if-else syntax mid-editing because it thinks its a malformed if-else block until it’s completely finished should tell you that you’re probably going about this the wrong way.

Frankly, if you don’t have the balls to remove the ternary operator entirely, don’t give it some confusing coat of paint to make it “more obvious.”


#136

I, for one, emphatically throw my hat into the ring AGAINST the standard C-style ternary operator

And this is definitely unnecessary functionality with if-else expressions.

The phrase you are looking for is “easier to read”.

ternary operator is the most lopsided operator there is because it is a postfix on the condition. Imagine reading from right to left, x = a, ok a gets assigned to x, now ?, WTF? x = a ? b, WTF?, x = a ? b :, Huh?. Compare that to x = if, OK at this point I know x is getting assigned the result of a conditional.

The phrase you are looking for there is “hard to read” or “unobvious”. And they will likely have to repeatedly look it up.

They see that and they already know what an if-else is. Only difference is that it has a value instead of continuing the artificial Java and C limitation that if has no value. Lots of other languages already have if-expressions and this is easy for them to read. I think a non-programmer could figure out what x = if(a) b else c means.

Certainly no one is talking about removing conditional expressions. Ternary operator exists ONLY because in C if was a statement not an expression. With that limitation gone ternary operator has no reason to exist.


#137

It’s interesting to compare Swift’s reasoning for having the ternary operator instead of if else as expression.

In this message Chris Lattner lists the cons of if then else expression:

  • It is substantially more verbose than ?:, so much so that it obscures the logic that was trying to be captured.
  • It looks like if statement, however it is semantically different
  • It forces indenting a lot when branches have long expressions

Then he lists the pros of the ternary operator:

  • It is extremely concise, and covers a very common pattern.
  • It is pervasively standardized in a very wide range of languages.
  • It’s weird syntax reduces the odds that people would flow it out and use very large expressions in it.
  • It chains well for multiple conditions because of its associativity.

However he also admits the cons of the latter:

  • ?: is ugly and magic, and is an additional thing people have to learn if coming to swift without encountering a C family language.
  • it is unfortunate that it uses “?” in particular, since they’d prefer that to be associated with optionals.

And here he even said that he’d love to see the weird ?: ternary operator get nuked and replaced with an if/else expression of some sort.

The links were taken from Commonly Rejected Changes page, so I believe these messages represent the Swift team’s point of view.

In the end he says “we only change things when there are strong reasons” and I think this applies to the situation with the ternary operator in Kotlin too :wink:


#138

+1 for ternary

I hate that everything for ternary is on place and you can in fact create one:

operator fun <T> Boolean.plus(firstValue: T): FirstValue<T> = FirstValue(this, firstValue)
operator fun <T> FirstValue<T>.minus(secondValue: T): T = if (bool) firstValue else secondValue
data class FirstValue<out T>(val bool: Boolean, val firstValue: T)

fun test(){
    val biggerTitle = (3 < 2) + "positive" - "negative"
}

but you need to use some other operators like plus minus or other names and therefore its out of standard and much harder to understand!

I dont really understand why to include e.g. array def via [] but not ternary.


#139
fun <T> Boolean.thenElse(onTrue: T, onFalse: T): T = if (this) onTrue else onFalse**
fun <T> Boolean.thenElse(onTrue: () -> T, onFalse: () -> T): T = if (this) onTrue() else onFalse()

val isConditionSatisfied: Boolean = ...
val result = isConditionSatisfied.thenElse("something1", "something2")

#140

+1 for Ternary

Ternary operator is definitely more elegant than if/else. With them you can write very readable multiline expressions like:

String value = (storeType == StoreType.Database)
        ? getDatabase().getSettingsDao().getString("my value")
        : getSettingsHelper().getSharedPreferences().getString("my value")

You just can’t write it with if/else to be nicely formatted. This is just one example I took from my head but I encounter such patterns at least few times a day.

IMHO if/else should be if/else, not ternary. It is a plus that you can assign them as expressions but only a plus. It shouldn’t forbid proper ternary operators. Maybe it’s me but It just doesn’t look nice and much harder to read. Also I always catch myself on trying to avoid if/else (ternary) at all because of that.


#141
String value = when(storeType == StoreType.Database){
   true -> getDatabase().getSettingsDao().getString("my value")
   false ->  getSettingsHelper().getSharedPreferences().getString("my value")
}

//misuse takeIf, but it looks more like your code
String value = takeIf{ storeType == StoreType.Database }
    ?.let{ getDatabase().getSettingsDao().getString("my value") }
    ?: getSettingsHelper().getSharedPreferences().getString("my value")

I personally use when most of the time.


#142

When is more verbose and you should understand that takeIf/let/?: looks ridiculous. Understand, I’m not looking for workarounds as I can come up with lots of them myself.

I don’t understand why a lot of people support Elvis operator and are against ternary one. They essentially have the same story and very similar in implementation:

Elvis transforms
if (a != null) a else b
into
a ?: b

And ternary transforms
if (condition) a else b
into
condition ? a : b


#143

As explained above (like a million times) the ? in Kotlin is an character associated with nullability. IMO this is the main reason why the ternary operator would not really fit into Kotlin. Also as explained above, the fact that if else are not statements but expressions means that the ternary operator is not needed. Yes it would be a bit shorter and some people argue even more readable, but it would not add anything new to Kotlin.

The reason why languages like Java or C++ have the ternary operator is because they can’t do stuff like

int foo = if(someCondition) 1 else 2;

They would need to write this:

int foo;
if(someCondition)
    foo = 1;
else
    foo = 2;

The fact that Kotlin treats if else as an expression and not a statement means that Kotlin basically already has a ternary operator (just with a different syntax).

I personally would support the ternary operator if not for the ?. I think it should not be used outside of the context of nullability.

As to the fact that if else is to verbose. I personally don’t like either syntax inside of a more complex expression as both tend to become to verbose in more than just the most basic examples. In those cases I just usually just declare a temp val. This is the most readable way to solve this problem IMO. And when you declare a temp val it does not matter whether you use if else or the ternary operator:

String value = (storeType == StoreType.Database)
        ? getDatabase().getSettingsDao().getString("my value")
        : getSettingsHelper().getSharedPreferences().getString("my value")

val value = if(storeType == StoreType.Database) getDatabase().getSettignsDao().getString("myValue")
else getSettingsHelper().getSharedPReferences().getString("myValue")

The only problem with this so far is the fact that the code style rules don’t really support proper alignment and indentation. But once you are used to this, not indenting the else is not even that bad (even though I would prefer it to be indented).


#144

It is a good sign for Kotlin that this (superfluous) discussion is one of the most popular here. It seems like Kotlin doesn’t have any real problems :wink:

Is there some design document with a reasoning why the conditional operator (ternary operator is a bad name) is not included in Kotlin and never will be? This document could be linked here so that this discussion could end.