ma11hew28
ma11hew28

Reputation: 126457

Does Swift have an “or equals” function like ||= in Ruby?

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

Answers (4)

Daniel T.
Daniel T.

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

caram
caram

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

JAL
JAL

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

user887210
user887210

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

Related Questions