Ternary conditional operator in Swift: What usage?

Linh NGUYEN
6 min readAug 31, 2018

--

Developers are familiar with ternary operator (or more precisely ternary conditional operator). It is not Swift-specific but a basic operator in many programming languages. How should it be used in Swift? To a lot of developers, "this way or that one?", it is just a matter of preference & habit as long as the code still compiles & does the job. To me, it is an interesting question worth searching for an answer.

To begin with, here is the definition of Ternary operator on Swift.org :

The ternary conditional operator is a special operator with three parts, which takes the form question ? answer1 : answer2. It’s a shortcut for evaluating one of two expressions based on whether question is true or false. If question is true, it evaluates answer1 and returns its value; otherwise, it evaluates answer2 and returns its value.

The ternary operator helps flatten the code by decreasing 1 level of indentation, hence contributes to the resolution of the famous pyramid of doom with nested if-s.

For example, this code

let duration: TimeIntervalif progress < 0.2 {
duration = 1.0
} else {
duration = 2.0
}

can be shortened in an elegant way by using this ?: pattern

let duration: TimeInterval = progress < 0.2 ? 1.0 : 2.0

Neat!

Personally, I love using this operator in my code. Whenever there is a need for branching, I wonder if I implement with a ternary operator instead.

However, in some cases, I still prefer if or switch.

Case #1 : When there is a harm to the code readability

Ternary operators often make the code more compact, but they should not be chained or nested. I agree that you can have fewer code lines when doing that, but then they may hurt your eyes (& others’) :)

Let's assume I have an enum named BatteryLevel:

enum BatteryLevel {
case invalid
case low
case medium
case high
}

Now, I want to add there an initializer init(percentage: Int). I can do this:

init(percentage: Int) {
self = (0...20) ~= percentage ? .low : ((21...50) ~= percentage ? .medium : ((51...100) ~= percentage ? .high : .invalid))
}

And because the ternary operator is right-associative, I can remove some parentheses to have this:

init(percentage: Int) {
self = (0...20) ~= percentage ? .low : (21...50) ~= percentage ? .medium : (51...100) ~= percentage ? .high : .invalid
}

The code becomes a bit less confusing, but I think switch is a better choice

init(percentage: Int) {
switch percentage {
case 0...20: self = .low
case 21...50: self = .medium
case 51...100: self = .high
default: self = .invalid
}
}

Case #2 : When I judge that the ternary operator is not used in a proper way

Recently a colleague assigned me a pull request & asked me to review his code. I stopped at a line like this:

shouldExpand ? expand() : collapsed()

The code compiles. It works. No problem. But wait, there is one.

I remembered in another project the team leader showed me a similar code line & asked if I could find anything "wrong". Well, it was about the return type of expand() and collapse()Void. According to my knowledge by that time, a Void method doesn’t return any value. While the ternary operator expects answer1 & answer2 parts (see definition on the top of the page) to return values, it seemed to me that Void should not be regarded as applicable.

This time, my colleague argued that in Swift, Void is in fact an empty tuple.

As Apple says about Void:

typealias Void = ()

When declaring a function or method, you don’t need to specify a return type if no value will be returned. However, the type of a function, method, or closure always includes a return type, which is Void if otherwise unspecified.

Use Void or an empty tuple as the return type when declaring a closure, function, or method that doesn’t return a value.

This still did not convince me. For a method returning an Int, for example, the Int result is what it is all about. For a method returning Void (or empty tuple, or no useful value), what is done before returning is important. 2 Void are always equal (answer1 == answer2 gives true), there is no interest to compare them. As I understand, the ternary operator, by its definition, is a choice between 2 values, not 2 side-effects.

Therefore, once again, I maintain the thought that ternary operator should not be used on Void.

If it was me, I would write the code with if

if shouldExpand { 
expand()
} else {
collapse()
}

If a Java/C# developer uses the ternary operator this way, he will get a compile-time error. In Swift, the compiler accepts the expression & does not throw a such error. Is Swift easy, or am I hard then ? :))

Case #3 : When there is a considerable Prettiness / Performance trade-off

Sometimes I saw discussions about the execution time & the complexity of different methods/different ways to do a thing, but I did not take so much attention. I always did some code optimization before finishing a task but eventually I knew that was not enough.

An article on build time that I read not long ago points out that using ternary operators may result in much longer build time.

I tried some same changes to my project & saw that they did actually improve build time (according to the provided tool). That was when I started to care more about the performance of the code.

While preparing this post, I ran a simple code, the 1st try was with an if, the 2nd one was with a ternary operator ?:. Below is what I got:

The difference was remarkable.

Sometimes we only need true or false case of if. The ternary operator always requires both, one of which may be redundant & will more or less affect the performance.

Even when I handled both cases of if , it still worked considerably faster.

Well, sometimes it is difficult to have both performance, readability & compact code. The choice is yours.

I suppose that the ternary conditional operator can be used in place of if in most cases to help make the code shorter, but it is absolutely not a replacement of if. This operator is a great choice in simple cases, while in the others, think about completing the task in a more classic way.

These are my personal experiences on the ternary conditional operator. Please feel free to give claps if you find my post helpful, to leave comments & to correct me if you think I am wrong on any point. Happy coding!

--

--