Ternary operator

I’d suggest you to consider using if expression in Kotlin. This is pretty idiomatic:

return if (!response.isSuccessful()) "fail" else response.body().string()

It becomes slightly better if you flip it:

return if (response.isSuccessful()) response.body().string() else "fail"

And you if are actually designing your own Kotlin API for response object, then you can make body() return null when response is not successful, and the usage is going to be even better with Kotlin’s elvis operator:

return response.body()?.string() ?: "fail"
26 Likes
response.body()

is “never null” as documentation says.
another example is:

result = (!response.isSuccessful()) ? "fail" : response.body().string()

because i have to add some things like:

response.close()

before i

return result

i thought to write something like this:

result = if (!response.isSuccessful()) "fail" else response.body().string()

and it is ok, but it looks verbose

1 Like

If you happen to find yourself writing this kind of code often, then you can consider defining an extension function like this one for the corresponding Response class (whatever it is the actual class you are using):

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

with this extension function your code reduces to

return response.bodyOrNull()?.string() ?: "fail"
6 Likes

i suppose it is useful to write the extension function if i would use it many times. But in this case it looks redundant, since i wrote

if (!response.isSuccessful()) "fail" else response.body().string()

only in one method

1 Like

I think your idea (bodyOrNull) is only useful in some special cases. The purpose of ternary operator is for more general cases. The main advantage of using ternary operator is making code concise when the logic is short. This kind of logic happens very often in real life. Let’s compare these 2 versions:

val v = if (b) x else y // 23 chars
val v = b ? x : y // 17 chars (saved 6 chars = 26%)

In the case of @edgeone:

result = if (response.isSuccessful()) response.body().string() else "fail" //74 chars
result = response.isSuccessful() ? response.body().string() : "fail" //68 chars (saved 6 chars = 8%)

IMO, saving 26% of time for typing in first case is really a good deal, plus the code in 2nd line is very clean and easier to read. For the later, we can only save 8% of time. If the expression is longer, it would be better to use if/else and separate into multiple lines to improve code readability.

I am really wonder why Kotlin doesn’t support this feature. The goal of Kotlin is to be better than Java, but in this case, it is not.

6 Likes

Writing code with the least number of characters is definitely non-goal for Kotlin.

19 Likes

Of course, we must always check for other perspectives. Therefore I asked: “why Kotlin doesn’t support this feature?”

If the feature is only a good thing, does not prevent other features and used commonly, then it should be supported (or at least plan to do it if it is not yet so important).
In the case of “optional semicolons”, Kotlin has the right decision because it saves developers’ time and make them happy. Ternary operator will also do the same job.

1 Like

I think that this page gives a pretty exhaustive answer on this question: https://kotlinlang.org/docs/reference/control-flow.html

In Kotlin, if is an expression, i.e. it returns a value. Therefore there is no ternary operator (condition ? then : else), because ordinary if works fine in this role.

6 Likes

I believe Kotlin lacks ternary conditional operator because it was impossible to get it into the grammar at the point the language was designed. For example, colon : was used to do static type assertion:
val c = someList: Collection // now c is Collection<T>

That syntax was removed before 1.0, but I’m not sure is there any syntactical obstacles left for ternary conditional operator.

8 Likes

@elizarov: the reason in kotlin docs does not really convince me :slight_smile:
@ilya.gorbunov: “static type assertion” you mentioned is a good reason, IMO.

2 Likes

Total unnecessary nitty gritty side-note: Can we please call this thing “conditional operator” or “conditional ternary operator”, but not “ternary operator”? Thank you! :blush:

3 Likes

I usually use “conditional operator”, but most people like the term “ternary operator” :smile:

1 Like
2 Likes

Ternary shorthand doesn’t seem useful in Kotlin since Kotlin’s if/else is already an expression.

At best, it saves a whole four characters at the expense of adding more syntax to the language. Or it ever-so-slightly increases the brevity of code that was already trivial to begin with.

It’s nice in a language like Javascript when if/else is a statement and rather unwiedly

Frankly, I think this sort of error handling is best done with a short-circuit rather than branching it against the success case.

if (!response.isSuccessful()) return "fail"
return response.body().string()

Especially since, as you point out, tend to need more logic in the success path.

(Couldn’t pass up a good bike-shedding opportunity)

3 Likes

i think, the bigger any project will be, the more one will need to write if/else, and because of that, in a strategic point of view it looks like it would be better to add a ternary operator in the compiler

Care to elaborate?

implementing a ternary operator in the compiler is a task what will be done once.
Writing if/else instead of a ternary operator in each project will cost more than adding a 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.

6 Likes