[swift-evolution] [Review] SE-0018 Flexible Memberwise Initialization

Matthew Johnson matthew at anandabits.com
Mon Jan 11 15:21:30 CST 2016


> On Jan 11, 2016, at 1:44 PM, Jordan Rose <jordan_rose at apple.com> wrote:
> 
> Sorry to leave this over the weekend before getting back to you! Planning to respond here, then go catch up on the thread—a possibly questionable ordering of tasks, but one that ensures I will actually respond at all.

No problem.  Thanks for responding!  

> 
>>> 
>>> - Given that these initializers are based on access control, is "public memberwise init(...)" different from "internal memberwise init(...)"? Can I put both in the same type?
>> 
>> If you have at least one internal property they would result in different signatures so would not be a duplicate declaration.  The public memberwise init would obviously need to initialize the internal property somehow.
> 
> That's what I expected, just wanted to have it spelled out. Thanks.
> 
> 
>>>  It seems like a big, complicated feature that "does what you mean" only when it's first added and then becomes an impediment to any later change.
>> 
>> I can certainly sympathize with this.  It is the big drawback of the automatic model.  At the same time, this proposal builds on the existing memberwise init for structs and doesn’t really make the rules that much more complex.  But it does make the feature more prevalent and visible, thus making it more important to understand the rules.  And of course it could be argued that the current memberwise init is too complex as it is.
>> 
>> For the record, here is a concise list of how this proposal expands the current memberwise init:
>> 
>> 1. Allow the memberwise initializer to be used in classes
>> 2. Allow default parameter values for `var` properties
>> 3. Fix the problem the current memberwise initializer has with lazy properties
>> 4. Use the `set` rather than `get` visibility for `var` properties
>> 5. Allow you to request the memberwise initializer, including:
>> 	i. Add additional parameters
>> 	ii. include an initializer body
>> 	iii. Specify access level, which will result in omission of memberwise parameters for more-private properties (it would be reasonable to limit this to private and internal if concerns about allowing it to be public are a significant factor)
>> 
>> I am curious to hear your thoughts on which of these points are not desirable, and what your opinion is about the existing rules for the implicit memberwise init for structs.
> 
> I'm happy with 1, 2, and 3 as a separate proposal, or several separate proposals. (For 1 in particular, the restriction predates the access control model, but making it implicit would also interfere with inheriting designated initializers.) I'm not sure 4 is interesting enough, but sure.

Hmm, thought you had agreed with #4 in the discussion about that topic.  That said, it is less important in the context of an `internal` or `private` implicit memberwise initializer. 

> 
> The particular concern I have with 5 is that the most interesting use case to me is for 'public' (indeed, that's by far the majority of the requests for this we've seen in Radar, rdar://problem/18065955 <rdar://problem/18065955>), but that's also the most dangerous one if you have anything unusual going on: different access control, library evolution, etc. (i) and (ii) are mostly just extra features, but (iii) is where it gets weird.

I can certainly understand your concerns regarding `public` as well as (iii).  

I’m hoping this proposal will be accepted even if some features are removed.  Even if only 1-3 or 1-4 were accepted to improve the implicit memberwise initializer I would consider that a good thing.  

> 
> (The next most common request related to this proposal is 1, memberwise inits for classes, mostly in simple cases. rdar://problem/16704095 <rdar://problem/16704095>)
> 
> For public memberwise inits, I think my discomfort ultimately comes down to "the order of stored properties in a class is not usually part of the class's ABI", and this makes it too easy to opt into that, and then too hard to explain which members and why. There's also the problem of wanting to tweak one parameter's behavior, and being unable to do that; having to build more features on top of this one to fix that seems like it's going in the wrong direction.

I hope you’ll take a look at the new proposals I submitted.  I think they provide a better approach to providing this kind of control than the enhancements I included in this proposal.  The Partial Initializers proposal might be the best one to look at first.  It would effectively supersede the explicit memberwise initializers in this proposal with a more general purpose implementation.

> 
> 
>> 
>>> 
>>> I'm motivated to solve the tiny value struct case, the public C-like struct case, but I don't think I want this creeping into the interface of a public class. I'd rather go with the "annotation on parameters" solution (which would be a separate proposal, of course).
>>> 
>>> public struct Point {
>>>   public var x: Double
>>>   public var y: Double
>>>   public init(self x: Double, self y: Double) {}
>>> }
>>> 
>>> or
>>> 
>>>   public init(@assigned x: Double, @assigned y: Double) {}
>>>   public init(self.x: Double, self.y: Double) {}
>>>   // something else
>>> 
>> 
>> I’ll ask you the same question I asked David about this approach: if the parameter must be explicitly related to a property for assignment, why should we repeat the type information (and default value information if it is a var)?  Doesn’t it seem reasonable to omit the type?
> 
> I'm happy to come up with a syntax to omit the type and default value; I do still think the listing of parameters should be explicit. (And it should be obvious where it gets any type and default value from.)


Glad to hear you think we could omit the type and default value (but still allow for overriding the default value).  I think as a sugar feature it needs to save as much as possible to pay its way.

Another idea along the lines of paying its way as much as possible: maybe if all parameters are “self” parameters you could specify that once at the function level rather than repeating it for every parameter.  What do you think about that idea?  Maybe something like an @self attribute:

@self public init(x, y) {}

I agree that it should be obvious where those come from - I think the type and default value would come from the property declaration.  Is there anywhere else it could come from?

I think this feature could be useful.  I just don’t see it as being a complete solution.  It would combine with my new Partial Initializers proposal very nicely.

Matthew
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160111/bff082cf/attachment.html>


More information about the swift-evolution mailing list