Short-circuiting assignment operators

Hi all, apologies if this has been pitched before...

I wanted to propose adding three short-circuiting assignment operators I frequently find useful in my code to the standard library.

Nil-Coalescing Assignment Operator (??=)

This operator performs a nil-coalescing operation, replacing the wrapped value with a default value if the wrapped value is nil.

infix operator ??= : AssignmentPrecedence

extension Optional {
  public static func ??= (lhs: inout Self, rhs: @autoclosure () -> Wrapped) {
    lhs = lhs ?? rhs()
  }

  public static func ??= (lhs: inout Self, rhs: @autoclosure () -> Self) {
    lhs = lhs ?? rhs()
  }
}

Logical OR Assignment Operator (||=)

This operator performs a logical OR operation, replacing the value of the left-hand side with the result.

infix operator ||= : AssignmentPrecedence

extension Bool {
  static func ||= (lhs: inout Bool, rhs: @autoclosure () -> Bool) {
    lhs = lhs || rhs()
  }
}

Logical AND Assignment Operator (&&=)

This operator performs a logical AND operation, replacing the value of the left-hand side with the result.

infix operator &&= : AssignmentPrecedence

extension Bool {
  static func &&= (lhs: inout Bool, rhs: @autoclosure () -> Bool) {
    lhs = lhs && rhs()
  }
}

Rationale

These operators are syntactic sugar over the non-assignment counterparts, providing a more concise way to express in-place mutations. They also preserve the short-circuiting behavior, ensuring that the operators behave consistently with the non-assignment versions.

Note: Although short-circuiting can sometimes be confusing, having these assignment operators match the behavior of their non-assignment counterparts should make the code easier to understand for developers already familiar with short-circuiting logic.

Thoughts?

3 Likes

Some very good discussion here:

2 Likes