Swift regret: implicit initialization of Optional variables— Jordan Rose (@UINT_MIN) September 22, 2021
In Swift, stored properties and local variables aren’t initialized by default; the compiler makes you do it. Unless it’s Optional and mutable (var, not let).
Part of the Swift Regrets series.
In Swift, stored properties and local variables aren’t initialized by default; the compiler makes you do it. …Unless it’s Optional and mutable (
I don’t think I’d have bothered to elevate this to the list if it didn’t manage to cause performance problems, somehow. (The fact that a stored property is initialized to
nil shouldn’t necessarily be exposed to clients.)
But how did we get here? Well, in early Swift, we knew we weren’t going to follow C’s performance-over-safety choice of allowing variables to be totally uninitialized. (Turn on
‑Wuninitialized, everybody!) So at the very least the compiler was going to check. But we didn’t know how often people were doing this deliberately, or relying on Objective-C zero-initializing instance fields. ARC already zero-initialized local object pointers, so it wasn’t unprecedented to say that we’d do some kind of default initialization for simple types. That is, zero for integers and floats,
nil for Optionals, and
false for Bools.
Of course, this wouldn’t work on
let, because you can’t reassign a
let. But we didn’t know if we could convince people to use
let when C’s default is non-
const. Fortunately, it turned out people didn’t mind initializing things explicitly, and they loved
let…and 0 wasn’t always a good default, and it only worked for a few types anyway. So we took out all the defaults…except for
nil. Because that really is a sensible default.
(Aside: I argued for a long time that
false-for-Bool was a step too far; it’s not obviously a better choice than
true. @Gankra_ finally convinced me years later, but just barely.)
The thing is…if Optional is the only type that behaves like this, it’s weird. And it’s not an important thing for a learner to learn, so I bet plenty of people don’t know. Which is valid because it’s not that useful:
= nil isn’t that hard to type. (Though I’ll admit leaving it out seems appropriate for calling C functions with pointer out-parameters.) To add insult to injury, the compiler checked syntactically for the sugared form of Optional,
Int?. If you write out
Optional<Int>, you don’t get this behavior. (I think this was originally a layering problem in the compiler and now it’s a compatibility issue in edge cases.)
So now there’s behavior in the compiler to save five characters
= nil, which can cause performance problems in weird situations. (Specifically: types with inlinable initializers and Optional stored properties.) Hopefully the compiler folks can fix that part, at least.