Confusing evaluation order

Sorry, I know this is an old thread, but it's really the right place to point this out: the “strict left-to-right evaluation order” of Swift is a nice story we tell, but it isn't true. There's an inconsistency between mutating and non-mutating methods. All I have to do is add mutating before describe and the program works just as expected.

The fact that users don't notice the difference and aren't confused is a pretty strong indicator that “strict left-to-right” shouldn't be considered sacred, and the fact that we had to treat inout differently to make lots of useful programs work is a strong indicator that what we call “strict left-to-right” is in fact the wrong order.

This program demonstrates the differences in one place:

struct Y {
  func f<T, U>(_ x: T, _ y: U) -> (T, U) {
    print("-", (x, y))
    return (x, y)
  }

  mutating func g<T, U>(_ x: T, _ y: U) -> (T, U) {
    print("-", (x, y))
    return (x, y)
  }

  var me: Y {
    get {
      print("get access")
      return self
    }
    set {
      print("set access")
    }
  }
}

var x = Y()
let a = x.me.f(x.f(1, 2), x.f(3, 4))
print("----------")
let b = x.me.g(x.g(5, 6), x.g(7, 8))

The use of the me property is to show where acesses are evaluated. The output is

get access
- (1, 2)
- (3, 4)
- ((1, 2), (3, 4))
----------
- (5, 6)
- (7, 8)
get access
- ((5, 6), (7, 8))
set access

(if you use a _modify accessor it rums where the get accessor runs below the dashed line. And if you make Y noncopyable and replace get with _read, it runs where the get accessors run. So it's clearly not using the weird order in the first case due to x.f being interpreted as creating a closure that contains a copy of x.)

It's likely the ship has sailed, but IMO the right order is the one you get when everything is mutating. I'd characterize it as left-to-right, inner-to-outer. A left-to-right postorder traversal of the expression tree. It's consistent and non-confusing, and FWIW it's what I intuitively expect a language with specified evaluation order to do.

8 Likes