Sometimes I find myself writing swift 2 code like this:
class Test {
var optionalInt: Int?
var nonOptionalInt: Int = 0
func test() {
if let i = optionalInt {
nonOptionalInt = i
}
// do more stuff
}
}
where the problematic part is this:
if let i = optionalInt {
nonOptionalInt = i
}
In words: if optionalInt has a value, assign it to the variable nonOptionalInt, else do nothing.
Is there an equivalent way in swift 2 to express this in a elegant single line without adding an intermediate variable with if let i?
Edit
after contemplating the first answers...
Obviously there is an equivalent way
if optionalInt != nil {
nonOptionalInt = optionalInt!
}
Ternary operators ? : are not equivalent as they may trigger a didSet which the original code does not (good if this is a intended side effect)
The most elegant answer so far appears to be
nonOptionalInt = optionalInt ?? nonOptionalInt
it may also trigger a didSet like the ternary operator and therefore is not equivalent (also good if this is intended).
I think my wish to Apple would be something like
nonOptionalInt = optionalInt ??
or
nonOptionalInt ??= optionalInt
What you are looking for is the nil coalescing operator.
You would use it like so in this case:
nonOptionalInt = optionalInt ?? nonOptionalInt
EDIT
re: your last edit to your question:
"I think my wish to Apple would be something like nonOptionalInt ??= optionalInt
"
...why wish when you can build it? :)
I haven't thought about it enough to decide whether I would recommend something like this for the general case, but if it helps in your situation you can create a ??=
operator that does what you ask like this:
infix operator ??= {}
func ??= <T>(inout lhs: T, rhs: T?) -> Void {
guard let value = rhs else { return }
lhs = value
}
then, to see it in action:
let optionalNil: String? = nil,
optionalValue: String? = "optionalValue",
implicitlyUnwrappedNil: String! = nil,
implicitlyUnwrappedValue: String! = "implicitlyUnwrappedValue"
var a = "a", b = "b", c = "c", d = "d"
a ??= optionalNil // "a"
b ??= optionalValue // "optionalValue"
c ??= implicitlyUnwrappedNil // "c"
d ??= implicitlyUnwrappedValue // "implicitlyUnwrappedValue"
(note that you would add this definition at top-level scope, outside of the definition of any class, struct, or other type)
Swift 4.0 Version build from the 2.0er answer
/// Optional Assignment, assigns if value exists
infix operator ?=: AssignmentPrecedence
func ?=<T>(lhs: inout T, rhs: T?) {
guard let value = rhs else { return }
lhs = value
}
// Playground Test
var dummy = "old"
var opt :String?
dummy ?= opt // leaves old
opt = "new"
dummy ?= opt // value becomes new
Is there an equivalent way in swift 2 to express this in a elegant single line without adding an intermediate variable with if let i?
You can omit the intermediate value if you want to:
if optionalInt != nil {
nonOptionalInt = optionalInt!
}
And you can obviously put that all on a single line if you want:
if optionalInt != nil { nonOptionalInt = optionalInt! }
But you can also use the ternary operator if you prefer:
nonOptionalInt = (optionalInt != nil) ? optionalInt! : 0
where the 0
is just a default value to use in the case where optionalInt == nil
. If you don't want to change nonOptionalInt
if optionalInt == nil
then just use nonOptionalInt
:
nonOptionalInt = (optionalInt != nil) ? optionalInt! : nonOptionalInt
Note that the !
in optionalInt!
implicitly unwraps the optional value -- it's the way you tell the compiler that you know that optionalInt
isn't nil
so it's okay to assign to a non-optional variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With