Understanding precedence group's assignment in Swift 3.1

Viewed 1752

Swift allows to define our own precedence groups to use for our custom operators. There is one thing I struggle to understand and that is boolean assignment property.

From The Swift Programming Language (Swift 3.1):

The assignment of a precedence group specifies the precedence of an operator when used in an operation that includes optional chaining. When set to true, an operator in the corresponding precedence group uses the same grouping rules during optional chaining as the assignment operators from the standard library. Otherwise, when set to false or omitted, operators in the precedence group follows the same optional chaining rules as operators that don’t perform assignment.

It doesn't say much about the exact behavior of assignment property. What is the difference between assignment and non-assignment operators in optional chaining?

I defined ++= (behaving like +=) and ++ (behaving like +) operators along with AssignmentTesting struct for testing.

precedencegroup AssignmentTrue {
    assignment: true
}

precedencegroup AssignmentFalse {
    assignment: false
}

infix operator ++=: AssignmentTrue
infix operator ++: AssignmentFalse

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

    static func ++ (left: Int, right: Int) -> Int {
        return left + right
    }
}

struct AssignmentTesting { var number = 0 }

var assignmentTesting: AssignmentTesting? = AssignmentTesting()
assignmentTesting?.number ++= 3 // assigns 0 + 3 to assignmentTesting.number
assignmentTesting!.number ++ 5 // returns 3 + 5
assignmentTesting?.number // == 3

How do assignment: true and assignment: false influence these behaviors? Any explanation is highly welcomed.

3 Answers

A binary operator, even one that does not perform an assignment, may be included in a precedence-group with assignment: true. In this case, if the left operand uses optional chaining (and does not fail because it is nil), the operator will act on the value hidden behind the optional. The returned result will still be an optional.

In the case of assignment: false, the operator will just see the operand as an optional rather than the type of value it needs, and an error will follow.

In your code, replace the line:

 assignmentTesting!.number ++ 5

with the line:

assignmentTesting?.number ++ 5

If you set AssignmentFalse as the precedence-group for the operator ++, you will get an error. If you set AssignmentTrue, it will work, adding 5 to the value 3 hidden behind the Optional, and return Optional(8).

Related