Swift regret: inout syntax— Jordan Rose (@UINT_MIN) December 28, 2021
Swift has a notion of inout parameters, which are formally copy-in/copy-out (or perhaps move-in/move-out), and optimized to by-ref when possible. This is written `inout Foo` in the parameter type…and `&foo` at the call site.
Part of the Swift Regrets series.
Swift has a notion of inout parameters, which are formally copy-in/copy-out (or perhaps move-in/move-out), and optimized to by-reference when possible. This is written
inout Foo in the parameter type…and
&foo at the call site. Everyone would guess that this
& is in imitation of how you pass things by reference in C, by taking the address, and everyone would be right. But it’s not the same operation in Swift, and Quinn (@justkwin) has a post explaining how and why.
To make things more confusing but also necessarily practical, Swift does guarantee that if you use
& with a global or static property that’s stored without observers (
didSet), then you will get a consistent pointer value every time. (Though Jens Ayton points out that it also has to be a non-zero-sized type.) Fun fact: this wasn’t really about proper pointers at all, but rather APIs that use an opaque
void * as a unique ID, including the non-block-based Key-Value Observing APIs. It was a common idiom to use the address of a private static, and we didn’t have an obvious replacement.
I forget if we extended the “stable address” guarantee to class instance stored properties as well. The “The Swift Programming Language” book doesn’t say anything about either exception (that I saw), but I’m confident in the global/static one.
Anyway, if you read Quinn’s article you’d know that the analogy with C is more trouble than it’s worth. So what would I choose instead?
inout foo, just like the declaration. We had considered this but figured it would be too noisy…but I think we didn’t account for most
inout happening implicitly through
mutating, which isn’t confusable for an address and doesn’t require any annotation at the call site. (Getting away from Cocoa’s out-param-based error handling in Swift 3 helped too.)