PrePitch: Optional variables should require explicit initialization

Hi Team,

I wanted to bring up the current magical behavior of Optional auto initialization to nil when using ?

Currently in swift you can declare an Optional variable in this way

var foo: String?
print(foo) // prints nil

swift will automatically assign .none to the value. The above is somewhat equivalent to the below code.

var foo: String? = nil // .none
print(foo) // prints nil

but this behavior is only available when using ?. The below does not work.

var someValue11:Optional<String> 
// print(someValue11) // error: variable 'someValue11' used before being initialized 

I think this behavior is confusing specially when dealing with implicit unwrapped optional.

var someValue33:String!
_ = someValue33 + "?") // Boom Crash. No different from an uninitialized variable error

I propose that we deprecate this to make swift more consistent.

var foo: String?
// print(foo) // error: variable 'foo' used before being initialized. <Insert fixit here to add = nil>

What does the community think?

15 Likes

I don't see how the calculus has changed. It's a trivial rule to learn and saves more than it hurts.

5 Likes

It's also confusing because it applies to local variables but not to properties.

It applies to var but not let, both for local variables and properties.

5 Likes

Well the fact that I got that wrong just shows how confusing it is! :slight_smile:

7 Likes

I'd be very happy to see the implicit initialization removed. In addition to the issues mentioned in your pre-pitch, I want

  var x: Int?
  if b {
    x = 1
  } else {
  }
  use(x)

to tell me that I haven't initialized x on all paths like it does for any other type.

13 Likes

Undocumented extension of this feature: tuples of optional types are default initialized as well.

var x: (Int?, ((Bool?, Int?), Int?))
print(x) // prints (nil, ((nil, nil), nil))

If we remove this behavior, we should document that the tuple behavior is removed as well.

12 Likes

This would clean up a lot of implicit rules and edge cases in the compiler! :smile:

1 Like

i know what the rule is but at this point i’ve taken to just always writing out the nils to avoid confusion with let deferred initialization. will attest that i too find this pretty confusing.

3 Likes

I've run into problems a handful of times where I forgot to set an optional property during initialization because it defaulted to nil. I'd be happy to see this rule removed mainly for that reason, but also because it's a special case rule that doesn't pull its weight in terms of convenience imo.

11 Likes

Then make that property non-optional? Perhaps you are tracking some state where, instead of an optional, it would be better to use your own enum with cases named after the states + associated values for the data.

Since most people above seem positive to this pitch, just want to add a -1.

I agree that a custom enum is sometimes more appropriate than an optional, but not always. In cases where an optional is more appropriate, I wouldn't want to create an enum just to protect against this issue.

2 Likes

I'm +1 on this. I don't feel it pulls it's weight, and I agree with @taylorswift about the let deferred initialization issue.

1 Like

+1 as well for the reasons above.

I don't normally post here, but I also wanted to balance things out a bit with a -1.

Personally, I find it convenient to declare and initialise optionals with nil in one go (sort of like the opposite to type inference for non-optional variables, i.e. writing out the type instead of the value). Despite the anecdotes above, the rule also seems straightforward.

(Equally, I'm one of the weirdos that liked doing var x = Int?() in the Swift 2 days, so make of that what you will!)

2 Likes

to protect yourself from missed initialisation in that case when you have if else I use let

it is like init with default parameters but for Optional, isn't it?

+1. There is no reason for a special case implicit initialization.

2 Likes

+1

With this change, would all @IBOutlets have to be explicitly initialized to nil then?

@IBOutlet var label: UILabel! = nil

8 Likes