[swift-evolution] [Proposal] Uniform Initialization Syntax

Gor Gyolchanyan gor at gyolchanyan.com
Thu Jun 8 09:52:36 CDT 2017


Could you please elaborate why #1 and #3 would violate the rule?

About #1:

Currently, before all members are initialized, attempts to call to `super.init` or escape `self` will be met with a compile-time error.
The idea behind `self = nil` is to mark the initializer as `going to fail on return`, which simply fails the initializer upon return, while allowing members to be left uninitialized (which is exactly what happens if you `return nil`).
The only way to avoid failing the initializer at this point is to directly assign to self.
Seems like in both of these scenarios there are not uninitialized members because either the initializer fails, of `self` is assigned a fully-formed instance.

About #3:

The idea behind `self.member = MemberType?(parameters)` is to first call the failable initializer of `MemberType` and in case it fails, immediately fail the enclosing failable initializer which the member is being initialized in. This guarantees that this member is either initialized, or the failable initializer returns nil immediately.

> On Jun 8, 2017, at 5:19 PM, David Sweeris <davesweeris at mac.com> wrote:
> 
> 
>> On Jun 8, 2017, at 05:09, Gor Gyolchanyan via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> Disclaimer: I do realize that any of the following ideas may have been discussed before and/or there might be a good reason for their lack of implementation, so please go easy in me. 🙂
>> 
>> 1. Arbitrary `self` Assignments In Intializers
>> 
>> The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.
>> 
>> 2. Arbitrary `return` Statements In Intializers
>> 
>> The second idea is to allow `return ...` inside all initializers, which should also, theoretically, be a simple rewrite to `self = ...; return`. This one is to complement the existing `return nil` and allow some super-short initializers with a switch that returns in all cases or a more complex initializer that has a lot of guard statements.
>> 
>> 2.1. Future Factory Initializers
>> 
>> In addition, the `return ...` syntax has the benefit for potential factory initializers. So far, the proposals for factory initializers involved a keyword attached to the initializer, which just complicates the lexical structure of the language and adds unnecessary complication to the interface of types. Currently, factory initializers imported from Objective-C or from C using the `__attribute__((swift_name("MyType.init(self:...)")))` look like normal initializers (an in case of C, the return value doesn't even have to be related to the enclosing type in any way), but behave as you'd expect: you call the initializer and the result is a value that *should* be a subtype of the type you've called the initializer for. So, if in the future Swift gets native factory initializers (including, most importantly, in protocols), it won't require special syntax, because simply returning an instance of a subtype (with a compile-time check, of course) would look and behave very intuitively. This would also be very useful for singletons, which would use a private initializer for creating the instance and a public factory initializer for returning it.
>> 
>> 3. Failable Member Initialization
>> 
>> The third idea is to allow writing `self.member = MemberType?(...)` or `self.member = .init?(...)` (the exact syntax is up to debate) inside failable initializers, which would be simply rewritten as:
>> 
>> guard let _self_member = MemberType(...)  else {
>>   return nil
>> }
>> self.member = _self_member
>> 
>> This will dramatically reduce the boilerplate and visual clutter form complex failable initializers that call other failable initializers. A good use case would be complex `LosslessStringConvertible` types with many `LosslessStringConvertible` members.
>> 
>> So, what do you guys think?
> 
> #1 & #3 would violate Swift's rule about having to fully initialize all properties in inits.
> 
> My initial reaction is to like #2, though, assuming I understand it correctly.
> 
> - Dave Sweeris



More information about the swift-evolution mailing list