Insufficient documentation: Optional chaining assignment

It is apparently possible to write x? = y where x: T? and y: T. This is not made clear in the reference or the guide, with the reference merely making a passing reference to this possibility by stating

The unwrapped value of an optional-chaining expression can be modified, either by mutating the value itself, or by assigning to one of the value’s members.

Since all uses of optional-chaining expressions in the book (that I could find) are inside an expression with another subsequent postfix operator, a reader may believe this is the only possible use. Therefore, I suggest adding an explicit notice that this is possible, along with an example.

3 Likes

For instance, expand the example at the end of Expressions as such:

func someFunctionWithSideEffects() -> Int {
    return 42  // No actual side effects.
}

var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]

someDictionary["not here"]?[0] = someFunctionWithSideEffects()
// someFunctionWithSideEffects isn't evaluated
// someDictionary is still ["a": [1, 2, 3], "b": [10, 20]]

someDictionary["a"]?[0] = someFunctionWithSideEffects()
// someFunctionWithSideEffects is evaluated and returns 42
// someDictionary is now ["a": [42, 2, 3], "b": [10, 20]]

var someValue: Int? = nil

someValue? = someFunctionWithSideEffects()
// someFunctionWithSideEffects isn't evaluated
// someValue is still nil

someValue = 10

someValue? = someFunctionWithSideEffects()
// someFunctionWithSideEffects is evaluated and returns 42
// someValue is now 42
1 Like

Good catch :slight_smile: , cc @Alex_Martini

func bar () -> Int {
    return 5
}

do {
    var u: Int?
    print (u)
    u = bar ()
    print (u)
}

do {
    var u: Int?
    print (u)
    u? = bar ()
    print (u)
}

// Prints
nil
Optional(5)
nil
nil

This should be clearly explained in the book, also along with an example for the super useful, as @tera once remarked, pattern:

// Logging disabled
var printLog: ((String) -> Void)?

printLog? ("logging disabled")

// Enable logging
printLog = {print ($0)}
printLog? ("logging enabled")

// Prints
logging enabled