[swift-evolution] [Proposal] Partial initializers

Matthew Johnson matthew at anandabits.com
Mon Jan 25 20:43:38 CST 2016


> On Jan 22, 2016, at 1:12 PM, Jordan Rose <jordan_rose at apple.com> wrote:
> 
> 
>>>> 9. The compiler keeps track of the properties initialized by a partial initializer or initialization method and uses that knowledge when enforcing initialization rules in phase one in the calling initializer.
>>> 
>>> If a struct partial initializer is defined in another file, this would require reading the body of the initializer to determine what variables it initializes. We currently don't type-check any bodies outside of the primary source file when doing a normal, multi-process compilation.
>> 
>> Are you recommending a same-file requirement?  I wouldn’t have a problem with that.  I’m trying to keep this proposal as focused as possible and will make any changes necessary to address implementation considerations.
> 
> That would be one way to solve this, but that's kind of at odds with your direction of "partial initializers for stored properties in extensions”.

I included that discussion at John’s request.  He also mentioned that they wouldn’t necessarily share the same implementation even though they are conceptually similar.  I don’t think it needs to influence this proposal to the degree that we would exclude that option.  

I think a same-file requirement would be a reasonable place to start if the alternative is explicit declaration.

> There's also a circularity problem, where type-checking one partial init requires looking at the body of another, which mistakenly calls the first, but we can probably handle that error.

If partial inits calling other partial inits significantly increases complexity I could remove that from the initial proposal.  I don’t think it’s an essential feature.

> 
> The other way that comes to mind would be to explicitly declare what's being initialized, as Brent (and others?) mentioned. That's certainly not as concise but it does fix the problem.

I don’t like the idea of requiring this to be declared too much.  If we had “self.x” syntax and any “self.x” parameters implicitly declared the initialization of their corresponding property maybe it would be tolerable as would only need to explicitly declare properties set manually.

> I don't think it counts as a leak of information about stored properties as long as partial inits are never exposed publicly.

Agree. 

> 
>> 
>>> 
>>> Can an initializer method be overridden? If so, I assume that does not override the "initializer" part, just the "method" part? If not, can we require the 'final' to be explicit?
>> 
>> Good question.  I was thinking of them as implicitly `final` but didn’t call that out.  If you think they should be explicitly marked `final` I will make that change.
> 
> Well, I think it's a good idea. Others may disagree. It could also be required only for public init methods, because private and internal ones don't make an API contract.
> 
>> 
>>> 
>>> Can the method be marked @objc? 'dynamic'? I would assume "yes", because it's not really different from any other method, but I think it ought to be called out.
>> 
>> I suppose so if that doesn’t create any implementation challenges around the initializer aspect.
> 
> Yeah, they wouldn't apply to the initializer, only the method. I don't know if that's weird enough to forbid 'dynamic', but it seems benign for '@objc'. (AFAICT the effects of '@objc' are only observable after phase 1 completes anyway.)
> 
>>> 
>>> I don't personally like the call syntax but I don't immediately have anything better to offer. I do think that part of this proposal should include naming guidelines for these things.
>> 
>> I don’t love it but don’t have a better idea either.  It’s a good candidate for bike shedding and we might be able to find something better.
>> 
>> What do you have in mind in terms of naming guidelines?  I can imagine UI classes having partial inits like “appearanceProperties” and “animationProperties”, etc.  Those names wouldn’t be good for an initializer method though.
> 
> I think that does give us a place to start: initializer methods are named like methods but invoked in some special way. Maybe partial inits are named as methods as well. (Maybe we just drop partial inits to make everything simpler, and only have init methods. They can get dead-code-stripped if they're only used as partial inits.)

If we drop partial inits how would you recommend factoring out initialization logic that touches `let` properties?  It seems wrong to allow that in an init method.  The only way to support both `let` initialization *and* post-initialization calls is with two kinds of constructs.  They could share the same syntax, but that seems confusing to me.  That is why I included both of them in the proposal. 

> 
> 
>> 
>>> What happens when you call an init method from phase 2 of initialization? Is that just illegal?
>> 
>> Good question.  I should have addressed this.  Partial initializers should not be callable during phase 2.
>> 
>> It probably make senses to allow initializer methods to be called during phase 2 using the usual method syntax just like any other method.  What do others think?
> 
> I'm inclined to agree.
> 
> 
>> 
>>> 
>>> I'm ultimately still not convinced that this is the right way to reduce initializer boilerplate (phase 1 duplication between initializers, or shared code between initializers and methods). It again adds complexity to the language, and that added complexity may not be worth the payoff. I'm thinking about someone coming across the construct for the first time: would they understand what it was doing? Would they understand the error messages they would get?
>> 
>> What I like about this approach is that it is a general tool for factoring initialization code using techniques similar to those we use in other code.  Lots of people do similar things in Objective-C, but in an obviously unsafe way.  This would help ease their migration to Swift while helping them do this safely.
> 
> I do like the idea of "you can factor out code to helper methods, but initialization code is special, so you factor it out to special kinds of methods".
> 
> 
>> 
>> I think the best way to think about the added complexity is to consider the *incremental* complexity and benefit over Swift’s initialization model.  I think it is a pretty modest change to understand for those who already understand the existing rules while providing substantial benefit in some cases.
> 
> Heh. I don't think Swift's initialization model is exactly the part of the language we want to strive to emulate (even if all its corners are necessary in some sense). This feature doesn't interact much with most of the complexity there except the phase 1 / phase 2 part.

I didn’t meant this in terms of striving to emulate the initialization model.  Just that the feature is intricately related to DI and is wouldn’t be necessary without the phase 1 restrictions.  I think of it as a small enhancement to the init capabilities that provides a lot more benefit than it introduces complexity, especially considering how complex the init model already is.

> 
> 
>> 
>>> 
>>> (Specifically on that note: "init func" is probably okay because it's a special kind of func, but I think I would personally prefer to keep the 'partial' keyword for partial inits, even though it's technically unnecessary.)
>> 
>> I would be happy with whatever syntax the core team thinks is best.  I like keeping it more concise but don’t mind `partial` if others like that better.
>> 
>> It’s just hard to tell what that is with several people involved.  Any recommendations on how to handle this when writing a proposal? 
> 
> I don't think you'd know for real until it got to review. This list is high enough traffic that there are probably a lot of people who don't read the drafts, including members of the core team. :-/

Sure.  But it might be nice to be able to write a proposal “modulo syntax”.  We need placeholder syntax of course, but in many cases it might be best to allow that to be hashed out during review with the core team deciding on the final details if the proposal is accepted.  There have been several cases where this seems like an appropriate way to handle things.  What do you think?

-Matthew

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160125/3d477195/attachment.html>


More information about the swift-evolution mailing list