Reputation: 126457
In Swift, how do I set an optional foo
but only if it's nil
?
I know about Swift's nil coalescing operator:
foo = foo ?? "Hello"
(where foo
is an optional String
)
But, is there a better way, like in Ruby?
foo ||= "Hello"
Upvotes: 7
Views: 1954
Reputation: 33967
Such an operator was considered and rejected. Details can be found here.
The rationale behind the rejection is supposed to be in the swift-evolution email list, but the link attached to the above points to SE-0025 instead of 24.
The the original rationale is now at gmane.io. You can request access to the mailing list by searching for the "gmane.comp.lang.swift.evolution" group (partial credit to the user from the comments).
Upvotes: 10
Reputation: 1719
For Swift 5.1
infix operator ||=
func ||=<T>(lhs: inout Optional<T>, rhs: @autoclosure () -> T) { lhs = lhs ?? rhs() }
var foo:String? = nil // foo -> nil
foo ||= "Hello" // foo -> "Hello"
foo ||= "Hi" // foo -> "Hello"
See here for the reason why @autoclosure
is important: https://airspeedvelocity.net/2014/06/10/implementing-rubys-operator-in-swift/
Upvotes: 1
Reputation: 42459
For Bool
types in Swift 3:
infix operator ||=
func ||=(lhs: inout Bool, rhs: Bool) { lhs = (lhs || rhs) }
Usage:
var bool = false
bool ||= false // false
bool ||= true // true
bool ||= false // true
Upvotes: 1
Reputation:
Nope, that's the way to do it. If you want you can wrap it up in your own operator:
infix operator ||= {}
func ||=<T>(inout left: Optional<T>, right: T) { left = left ?? right }
var foo:String? = nil // foo -> nil
foo ||= "Hello" // foo -> "Hello"
foo ||= "Hi" // foo -> "Hello"
I'd recommend using ??=
to match the pattern foo = foo ?? "Hello"
but use whatever feels comfortable to you.
Upvotes: 6