Using if let someOptional { }
is convenient, but it also
means that the local unwrapped variable (or constant) makes
the original optional, having the same name, inaccessible
(a.k.a. variable shadowing).
Here are some possible solutions to unwrap-mutate-wrap
optionals with if let/var
without needing to come up with
a new name for the unwrapped local variable.
Since the $ sign can be used in variable names, the following
approach is currently possible. You still have to write the
variable name twice, though.
var n: Int? = 1
if let n$ = n { n = n$ + 2 }
print(n) // 3
Three prospective solutions follow here below.
(1) I pitched this some time ago, where pre
refers to a previous
variable outside of the inner scope.
var n: Int? = 1
if let n { pre.n = n + 2 }
print(n) // 3
Mutating more than one optional is possible:
var n1: Int? = 1
var n2: Int? = 2
if let n1, let n2 { pre.n1 = n1 + 2; pre.n2 = n1 + n2 }
print(n1, n2) // both are 3
Note that pre
could be used generally to access a variable with
the same name, but being defined outside of the local scope:
let i: Int = 5
if condition {
let i: Int = 2
print(pre.i + i) // 7
}
(2) Use assignment from if
statement. The rule would be that if
there is only one statement between braces, the word return
can be left out. If the optional is nil
, no assignment takes place.
var n: Int? = 1
n = if let n { n + 2 }
print(n) // 3
If there is more than one statement between the braces, my
suggestion would be to use the word use
instead of return
:
var n: Int? = 1
n = if let n { doChore(); use n + 2 }
print(n) // 3
(3) Differentiate (slightly less clear than the other solutions
since it relies on assumptions).
Use if let
, knowing that the optional is the one that it is
possible to assign to.
var n: Int? = 1
if let n { n = n + 2 }
print(n) // 3
With if var
, the local variable is the one that it is primarily
possible to assign a new value to. Then, if the optional should
be assigned to, do like this:
var n: Int? = 1
if var n { n += 2; n = n }
print(n) // 3
Other solutions are welcome.