PrePitch: Optional variables should require explicit initialization

Here to add my -1, especially for the IBOutlets case, and to keep the syntax as noise-free as possible

5 Likes

I think IBOutlet should provide default or delayed initialization via the new property wrappers feature. In that case it would not even have to be an optional. I’m asking on the other thread about this.

3 Likes

+1

Hand writing = nil is not a burden and making the following code compile would be a nice side benefit of the consistency we'd gain.

let foo: String?

if condition { 
    opt = "bar" 
} else { 
    opt = nil 
} 
5 Likes

I'm -1.

I think there's an argument to be made on both sides, but this would be a heavily source breaking change, (though admittedly with a fairly easy fix). There are also style guides / linters that have this behavior as preferred.

It is odd that var someValue11:Optional<String> doesn't default to nil, but that seems more like a bug than intentional.

Personally I prefer the cleanness of not having to set something that has a clear default.

7 Likes

There is no avenue that I know that we can approach Apple to change the behavior of their SDK other than bug reports but I don't why they could not move to a world were IBOutlet and friends use property wrappers.

@IBOutlet var label: UILabel // Okay! IBOulet using property wrappers for delayed init 
1 Like

This could also be a linter thing, especially since we apparently have people pretty strongly on both sides of the question. I've started working on a pull request to add this to SwiftLint, as an option on the existing redundant_optional_initialization rule which currently enforces not initializing optional var declarations with nil.

2 Likes

Assuming SwiftUI isn't going to be pushed so much that the old APIs will keep being updated with that kind of feature, I can't see it happening till next year. Assuming that's how it should work, (as we don't know the internals of Interface builder), I would imagine they would wait till propertyWrappers feature won't change.

I’m very supportive of this idea, I always found it confusing and inconsequent that optional vars of all things in the language had automatic initialisation.

+1 Less magic. Explicit over implicit. Bring it on!

2 Likes

I'm having a hard time articulating why, but I'm very much -1 on this.

nil is a "concept of zero" — where zero is something that denotes nothingness. nil is just another way of saying .none, but so is... nothing, as in, not specifying nil. I guess one of the reasons why var some: Int? feels correct is that you don't have to write out nil because it was already nothing to begin with.

With this context, I believe this is the special case for implicit initialization.

And arguments like...

...seem to contradict the rationale behind some great new features in Swift like @propertyWrappers and @functionBuilders where "magic" is promoted.

5 Likes

By this reasoning, shouldn't Int implicitly be 0? What about Array and []? String and ""?

Granted, Optional is an extra special type in Swift, but not much more than the ones I listed above.

9 Likes

I don't think so. Those types don't have the concept of "non-existence" baked into them. 0 is a valid integer just as much as 42 is, and an empty array is still an Array (same goes for String). They exist. nil, .none, are our way of saying that something explicitly doesn't exist.

It definitely is an extra special type and should be treated that way.

4 Likes

When designing APIs, authors are often confronted with whether or not to use nil or the empty string/array to denote no results. Most of the time, it doesn't matter which is chosen. Int and 0 were a poor example, but "" and [] are both equal representations of nothingness for their respective types, just like the .none case is for Optional.

7 Likes

Sure, that's fair, but the semantics of an empty array [] or a nil are just that: semantics, and should be left to the API designers to define. Most of the time it doesn't matter, but sometimes it does, depending on semantics.

Regardless, [] == nil will always be false. [] exists, it's something.

Right, I'm not arguing that nil == [], that's madness. I am saying that nil and Optional have the same relationship as [] and Array. Neither should get implicit initialization to their respective empty values.

4 Likes

This already compiles (assuming that the opts in the branches are meant to be foos). The implicit initialization does not apply to let.

let foo: String?
print(foo ?? "missing")    // error: Constant 'foo' used before being initialized

But like you said, Optional is a special type. Its nothingness is true nothingness in Swift, which is why var some: Int? is already correct and shouldn't need to be specified by explicitly declaring = nil. (Or at least this is why I think it feels correct. Again, it's difficult to articulate, so thanks for bearing with me.)

1 Like

Hmmm, so it does. I made a mistake there. Thanks.

If nil is "true nothingness," then how would you describe an uninitialized optional value, which entails the absence even of nil?

(And then consider the optional value being of type Optional<Never>.)

4 Likes

Again, as unsatisfactory as this might sound, it's a special case in Swift and should be (and already is) treated that way. var some: Int? is already an initialized Optional<Int> (as .none) which is as "nothing" as "nothing" gets in Swift. By specifying "nothing" you get "nothing" (nil, .none).