Ternary operator

It’s highly debatable that the omission will actually cost you, if any, it may actually save you some costs. Multiple constructs of the same type can make code more difficult to read. The less characters argument is easily debunked: we would be writing the shortest class and function names possible if that would actually saves use money, which it doesn’t.

So all this cutting cost is just speculating, we need actual numbers and studies if this is going to be the argument for a conditional operator.

1 Like

yes, i 100% agree with you, and an example lang to compare with could be groovy, it has both ?: binary operator and a ternary operator

1 Like

After a year of writing Kotlin code, I still start writing ? and catch myself when completions don’t work because the code makes no sense in Kotlin.

I have plenty of Kotlin if else expressions used but still prefer the elegance and aesthetics of the ternary operator, for short and shallow conditional expressions. I know and understand that the if in Kotlin and ? : are equivalent but that is not the point.

If else may be equivalent and only 4 characters longer but not as elegant for simple conditions and expressions.

It is definitely not an argument against Kotlin, which I find in general very elegant and highly productive, especially when compared to Java, but it is a minor nuisance.

For anything but short conditions and maybe one nesting level, I prefer the full if/else syntax which lends itself to better formatting to convey the logical structure.

It is not lack of Kotlin coding either, in my Markdown Navigator plugin Java and Kotlin code is about 50/50 with 60k lines of each. Kotlin being more terse, I would argue that I have more functionality implemented in Kotlin than Java.

I was hoping with time to get over ternary operator use but so far have not managed to kick the habit.

10 Likes

its ridiculous to have shortcut for ternary ?: but not ternary itself

8 Likes

kotlin have no snippets base to copy from yet. on stackoverflow eg
for now rewriting groovy and java code into kotlin is a common thing. for me at least
and things like no ternary, no collections syntax, no try with resources, different interpolations, different quotes, types on the wrong side, etc - just adds more hassles

what is it?

working on any kotlin project i only really need ternary operator, as i cannot get used to writing if\else as expression; i really starting to think about trying to add ternary operator in kotlin compiler myself

2 Likes

I’m talking about string interpolation compared to groovy
in groovy “$foo.bar” is “${foo.bar}” whereas in kotlin its “${foo}.bar”

Like others, after many years of writing programs in other C-family languages, I often find myself trying to type the conditional operator in Kotlin rather than an if/else expression.

However, I’m not sure that it would be a good idea to introduce the former at this late stage since when you see a ? in Kotlin you immediately think it must be something to do with nullability which, of course, it wouldn’t be here.

For those who think that an if/else expression looks verbose, another idea would be to write an ‘iff’ function which is fine for simple stuff:

fun<T> iff(condition: Boolean, result1: T, result2: T) = if (condition) result1 else result2

fun main(args: Array<String>) {
    val c = 10
    val d = iff(c > 10, 1, 2)
    val e = if (c > 10) 1 else 2 
    println("$d == $e")
 }

Incidentally, @guai, not sure what you mean about not being able to use “${foo.bar}” in Kotlin since, if you run the following code (in version 1.0.6 or later), you’ll find it works fine whereas “${foo}.bar” does not:

class Foo {
    val bar = 3
}

fun main(args: Array<String>) {
    val foo = Foo()
    println("${foo.bar} != ${foo}.bar")  
} 
3 Likes

@alanfo imagine you rewriting some groovy script using kotlin, gradle build perhaps, gradle team actually adapting kotlin right now
in gradle there was file("$project.buildDir/subdir") in kotlin you should instead write file("${project.buildDir}/subdir") cause "$project.buildDir/subdir" will give you something like “project :foobar.buildDir/subdir” and not the path. And you should fix all these lines manually, cause comiler will never see any errors here
JB guys borrowed some good things from other langs but aslo add some strange stuff, just to be different I think. I see no other reasons to change usual things that was never broken
That also violates the principle of least surprise
The lack of ternary is one of this annoying things

I do agree with you, @guai, that it’s surprising that you can’t just write: println(“$foo.bar”) and expect to see ‘3’ (in my previous example). Another disappointment is that there’s no shorthand for including formatting information within a template - you have to use String.format or a variation thereof.

To be fair, it does say in the documentation that the curly braces can only be omitted in the case of a ‘simple’ name. However, it doesn’t say that even a simple name needs to be wrapped in curly braces if the template is immediately followed by a letter, number or underscore (for example "${foo}_bar" rather than "$foo_bar").

This is presumably because foo_bar could be an identifier. So it looks like when a string template is parsed, the compiler doesn’t check immediately that the simple name is actually being used in a program - it leaves that to a subsequent pass which I guess is fair enough.

However, whilst I have some misgivings about string templates, I think there are plenty of other things which Kotlin does get right even if they are surprising to those coming from a Java, C# or C++ background. Sometimes you just have to break the mould to end up with a better language and, when one looks at other modern languages such as Swift, Rust and Go, it’s clear that the Kotlin designers aren’t the only ones to have come to this conclusion.

Or more elegantly,

fun Response.bodyOrNull(): String? = if (isSuccessful()) body().string() else null

and

return response.bodyOrNull() ?: “fail”

@ilya.gorbunov I guess this is the same reason scala too does not have ternary conditional operator.

Kotlin 1.1 added new takeIf that would replace the expression in bodyOrNull

response.takeIf{ it.isSuccesful() }?.body()?.string()

Note that most of those methods should really be properties not method calls. If the property does not exist you can create extension properties. It should be it.successful not it.isSuccessful()

1 Like

I think this
> return response.body()?.string() ?: "fail"
much cleaner than java did. Thanks kotlin team!

1 Like

I would vote to NOT add ternary operators to Kotlin.

I personally never understand the merit for ternary operators when you have if clause expressions as Kotlin does. Implementing ternary operators, in my opinion, has always just been a “crutch” because in languages like java, if statements are not expressions.

The primary purpose of ternary operators in other languages is so that people can “inline” their if/else expressions. you can do this natively with Kotlin if/else expressions already.

Same for Kotlin’s when clause. People would wrap switch statements in methods (in java) and return items all so that the calling function could store the result in a final variable. in Kotlin you can directly assign the result of a when expression! Awesome stuff! :slight_smile:

In your example, I’d rewrite it as:
return if (response.isSuccessful()) response.body().string() else "fail"
And note that even if a ternary operator existed, you’d only be saving a few characters with:
return response.isSuccessful() ? response.body().string() : "fail"
It doesn’t seem worthwhile to further extend the Kotlin syntax for so little gain.

3 Likes

Hello,

i aint believe you never used ternary operator in java/c++/swift/groovy, as ternary operator is a common pattern)))

1 Like

Yes, ternary operators, despite being confusing for at least beginning programmers, have their value. They are very easy to abuse for expressions that are not of very low complexity. One of their problems is that it is easy to “miss” their use or to loose track of it and an if statement would be more appropriate. My feeling is that the kotlin if expression makes this more explicit, including more clear “uglyness” in those cases where a more explicit control structure would be warranted.

In addition, the nullable type system and elvis operator reduce many of the more common needs for the ternary operator. Inline functions (taking other functions) could then be used to improve both reliability and readability.

3 Likes

yes, but not all, as ternary operator not only for null checking, ternary operator is a short form of if/else, and sometimes ternary operator is more appropriate than if/else, but those “sometimes” cases not actually “sometimes”, as they often occur, and the bigger the project, the more often ternary operator is needed, in my opinion

Readability is far more important than number of characters. I know that I have to read ternary conditionals at least twice before I can understand what is going on.

In the example above, when I read “if” I immediately know that I’m going to be evaluating a conditional. When the first character I see after the equal sign is another value I think assignment until I see the question mark and have to reread the line with a different context.

With the behavior of the if statement as it is, I can’t ever see myself favoring a shorter, harder read to read way to do the same thing.

3 Likes

I never said I never used ternary operators. I’ve used them thousands of times. I said I dislike them.

I also said was that they are ONLY useful in languages like java/c++/etc where the if statements are NOT expressions. i.e. they do NOT return anything. In java you couldn’t do what I was proposing to do with Kotlin because if statements in the languages you mentioned are inferior/weaker.

In Kotlin, since if statements are expressions, they can already do what you are wanting to use ternary operators for. Thus there is no need for ternary operators in Kotlin.

I recommend re-reading the exact details of my previous message.