5

Why does += not work with implicitly unwrapped optionals, for instance:

var count: Int! = 10
count = count + 10 // This works
count += 10 // this does not work

Why isn't the optional implicitly unwrapped, like the case of count = count + 10 ?

Hamish
  • 78,605
  • 19
  • 187
  • 280
  • 1
    The operator needs a reference. – Sulthan Jul 24 '17 at 20:34
  • can you explain it more? – Muhammad Zubair Ghori Jul 24 '17 at 20:53
  • the function "+=" expends an Int. You are giving it an Int!. – scord Jul 24 '17 at 21:26
  • 1
    You may append `?` to the left hand side of the `+=` operator , `count? += 10`, which likewise works if `count` is a "regular" optional, `Int?`. If its value is `nil`, the `+=` operator will do nothing, whereas if it is non-`nil`, it will do the work upon `.some(value)` to increase `value` by the right hand side. – dfrib Jul 24 '17 at 21:46
  • if this is the case so why here count = count + 10 (Int! + 10 ) is working? – Muhammad Zubair Ghori Jul 24 '17 at 21:49
  • It is more interesting to study why `count += 10` doesn't work. In the assignment `count = count + 10`, `count` in the right hand side will be treated just as a value and be implicitly unwrapped (as is specified for implicitly unwrapped optionals). The `count += 10` case, however, is just sugar for the call to the `+=` function providing a reference to _the value_ of `count` and a copy of the right hand side: `(+=)(&count, 10)`. But since `count` is an implicitly unwrapped optional, its (implicit) value is immutable, and this is equal to the call `(+=)(&(immutable_value_representation), 10)`. – dfrib Jul 24 '17 at 22:04
  • ... and you may naturally not pass an immutable property as an `inout` parameter (which is precisely what the `lhs` of the `+=` operator is). The key here is the immutability of the implicitly unwrapped value, which is also mentioned in the duplicate target. – dfrib Jul 24 '17 at 22:05
  • (... if `count` is explicitly unwrapped, as e.g. in my first comment above, the wrapped value (if it exists) can naturally be mutated if the property is a mutable one: it's only when the wrapped value is provided implicitly that the value representation will be immutable). – dfrib Jul 24 '17 at 22:12

1 Answers1

2

It doesn't work because the compound assignment operator += expects the left side to be a mutable Int variable. When you pass it count, the compiler unwraps the implicitly unwrapped optional and sends an immutable Int value instead, which cannot be passed as the inout parameter that += expects.

If you really want to do this, you can overload +=:

func += (left: inout Int!, right: Int) {
    left = left! + right
}

Now += sends the left side as an implicitly unwrapped optional without unwrapping it, and the unwrapping is done explicitly inside the function.

var count: Int! = 10
count = count + 10 // 20
count += 10 // 30
Robert
  • 6,660
  • 5
  • 39
  • 62
  • so why count + 10 is working ? – Muhammad Zubair Ghori Jul 24 '17 at 20:51
  • This answer is not correct. In the expression `count += 10`, `count` will implicitly be unwrapped into a concrete (`Int`) value, but that value _will be immutable_ (a property of the wrapped value representation of an implicitly unwrapped optional _when it is provided implicitly_). Since the first argument (or left hand side) of the `+=` method(/operator) is an `inout` parameter, naturally you may not pass immutable properties to it. – dfrib Jul 24 '17 at 22:09
  • (... The custom `+=` operator above just provides a more specific overload for the case when `lhs` is of type (`inout`) `Int!` and `rhs` is of type `Int`. This means there will be no need to implicitly unwrap `count` in the call `count += 10` (to match the overload `(+=)(inout Int, Int)`), since there is a perfect overload match for that call. The body of the overload, however, explicitly unwraps the wrapped value, allowing mutation of it). – dfrib Jul 24 '17 at 22:17
  • 1
    @dfri I didn't realize it was actually unwrapping the optional; from the error message I assumed it didn't even try. I edited my answer. – Robert Jul 24 '17 at 22:31