So I asked this question, and it looks like the reason
var num:Int! = 0
num++
doesn't work is because the ++
operator takes an inout
parameter, which implicitly unwrapped optionals are not. However, in
var num:Int! = 0
num = num + 1
the +
operator works with the implicitly unwrapped optional, meaning that the binary operator doesn't require an inout
parameter. So my question is, why do unary and binary operators have different parameter requirements? It seems kind of silly to me to be able to use an Int!
with only binary operators, but use an Int
with everything.
why do unary and binary operators have different parameter requirements?
Well, it isn't a unary vs. binary question. There are unary operators that work with Int!
. For instance:
var i: Int! = 17
var j = -i
-
is a unary operator and it works. The question comes back to the issue of inout
. The ++
prefix and postfix operators for Int
don't work with Int!
because the variable is passed as inout
(since ++
modifies the original variable in addition to returning a value). inout
requires the type to exactly match.
Note that implicitly unwrapped optionals are still optionals.
var i: Int! = 17
var k = i // k has the type Int!
var m = i! // m has the type Int
So passing an implicitly unwrapped optional as an inout
variable that requires the non-optional type doesn't work because inout
variables need to exactly match the type expected and Int
and Int!
are two very different types. The variable must either be explicitly unwrapped, or you need to provide an overloaded function that takes the optional type.
You might ask, why doesn't Swift just unwrap the Int!
for you and call ++
with the Int
? Well, ++
both modifies the variable and returns a value. If Swift unwrapped the Int!
and called ++
with an Int
, then the type of the return would be Int
. Then you'd have people on StackOverflow asking, "why does var i: Int! = 17; var j = i++
make j
an Int
instead of an Int!
?". To do it right, ++
needs to return an Int
when it is given an Int
, and return an Int!
when it is given an Int!
. So, what is needed in an overloaded function.
It is possible to overload ++
and make ++
prefix and postfix functions for Int!
:
prefix func ++(inout x: Int!) -> Int! {
return ++x!
}
postfix func ++(inout x: Int!) -> Int! {
return x!++
}
var i: Int! = 17
var j = ++i
print("i = \(i), j = \(j)") // "i = 18, j = 18"
j = i++
print("i = \(i), j = \(j)") // "i = 19, j = 18"
As to why the Swift designers haven't done this, only they know why.