# Conditional optional checks

I have two optional properties and would like to know how to elegantly unwrap them to perform a conditional check.

There is the bang operator solution, which I would prefer to avoid:

``````    let optionalOne: Int?
let optionalTwo: Int?

if oneCheck != nil && oneCheck > 0 || twoCheck != nil && twoCheck > 0 {}
``````

And the lengthy if let check:

``````    let optionalOne: Int?
let optionalTwo: Int?

if let oneCheck = optionalOne {
if let twoCheck = optionalTwo {
if oneCheck > 0 || twoCheck > 0 {
}
}
}
``````

Is there a more elegant Swift like solution than the two options above please ?

You can combine multiple `if` clauses into a single level!

``````if let oneCheck = optionalOne,
let twoCheck = optionalTwo,
oneCheck > 0 || twoCheck > 0 {
// â€¦
}
``````

ETA: though itâ€™s worth noting, your two examples arenâ€™t actually equivalentâ€”the version Iâ€™ve posted here only satisfies the condition if both optional shave a value, at least one of which is greater than 0, but your first example will satisfy the condition if at least one of the optional has a value and is greater than 0, which is subtly different behavior.

3 Likes

You could use the nil coalescing operator like so:

``````if (optionalOne ?? -1) > 0
|| (optionalTwo ?? -1) > 0 {}
``````
3 Likes

I've never seen this before, interesting.

BTW, I do not follow compiler logic here:

``````var v: Int? = nil

func test() {
v == 0  // can do this
v != 0  // and this
v > 0   // but not that?
// Error: Value of optional type 'Int?' must be unwrapped to a value of type 'Int'
}``````

The first two use optional promotion, and are comparing two optionals for equality.

The third line cannot do the same because there is no â€ś`>`â€ť operator for `Optional`.

3 Likes

I can do this myself:

``````extension Optional where Wrapped: Comparable {
static func > (a: Self, b: Self) -> Bool {
switch (a, b) {
case (.some(let x), .some(let y)):
return x > y
default:
return false
}
}
}
``````

and I guess something like this is already done for `==` and `!=`.

1 Like

â€¦right.

You said you didnâ€™t understand the â€ścompiler logicâ€ť, so I explained it.

The compiler rejects the code because no such operator exists.

If you are wondering why there is no such operator, thatâ€™s not a question about the compiler.

1 Like

The reason there is no such operator is that it was removed from Swift in version 3. At the time, conditional conformances were not possible, but the principal reason for the removal of these operators stands even today:

If `nil` can be compared with non-`nil`, then it has to be either less than any non-`nil` value or greater than every non-`nil` value (or else it breaks the semantic guarantees of `Comparable` like NaN, which we very much wouldnâ€™t want to do)â€”either choice can cause non-intuitive behavior in generic contexts when users do not anticipate optional promotion.

4 Likes