Sent from my iPad

> On Jan 6, 2016, at 8:43 PM, Joe Groff <[email protected]> wrote:
> 
> 
>> On Jan 6, 2016, at 6:31 PM, Matthew Johnson <[email protected]> wrote:
>> 
>> 
>> 
>> Sent from my iPad
>> 
>>>> On Jan 6, 2016, at 7:57 PM, Joe Groff <[email protected]> wrote:
>>>> 
>>>> 
>>>>> On Jan 6, 2016, at 3:39 PM, Matthew Johnson <[email protected]> 
>>>>> wrote:
>>>>> 
>>>>> 
>>>>> On Jan 6, 2016, at 5:08 PM, Joe Groff <[email protected]> wrote:
>>>>> 
>>>>> I find it surprising that you key the initialization of 'var's based on 
>>>>> whether their setter is visible or not. Initialization is not the same as 
>>>>> setting, and memberwise initializers within the definition have private 
>>>>> access to the member anyway; this is why `let` properties can be 
>>>>> initialized, after all. `private(set)` is also a way for an API to 
>>>>> communicate that a property is read-only without promising that it is or 
>>>>> will always be immutable, so I think it's important that a 'private(set) 
>>>>> var' be as capable as a 'let' to the maximum degree possible.
>>>>> 
>>>>> -Joe
>>>> 
>>>> Hi Joe,
>>>> 
>>>> Thanks for bringing this topic up and moving the discussion to the list 
>>>> (it’s hard to get into details on Twitter).
>>>> 
>>>> I am definitely sympathetic to the points you raise.  The problem is that 
>>>> there is no good solution to this without involving at least one of the 
>>>> future enhancements.  Chris feels strongly that we need to focus on the 
>>>> core functionality for the initial proposal so we must choose a solution 
>>>> without them.
>>>> 
>>>> Using the `var` setter visibility is the least bad option in my mind.  
>>>> There are many times when a var might represent internal state that a user 
>>>> is allowed to read, but should never be allowed to specify, whether via 
>>>> initialization or otherwise.  These will have `private(set)` visibility.  
>>>> 
>>>> If we allow memberwise initialization to expose them it will be a useless 
>>>> feature for types that contain a var like this.  There will not be any way 
>>>> to specify that they should not participate in memberwise initialization 
>>>> without at least one of the future enhancements.  On the other hand, if 
>>>> you do wish to expose them via the initializer it is easy to add a 
>>>> parameter and initialize the `var` manually.
>>>> 
>>>> This is also a safer solution.  The author of the type has specifically 
>>>> stated that users should not be setting the value of the `var`.  Maybe 
>>>> that doesn’t apply to initialization, but it is not the right decision to 
>>>> assume that IMO, at least without the ability to specify `init` visibility 
>>>> independently if desired.
>>>> 
>>>> In the case of `let`, if we do not use the only access control modifier 
>>>> they are allowed to have they would not be able to participate in 
>>>> memberwise initialization at all.
>>>> 
>>>> I think the proposal makes the least bad choice we can make without 
>>>> expanding it to include the ability to specify init visibility (which I 
>>>> would support if the core team was willing to do that).
>>> 
>>> 
>>> I'm not sure what you mean by init visibility.
>> 
>> The proposal suggests a possible future enhancement for specifying access 
>> control for init distinct from get and set like: 'private public(init)'.  
>> This would be available to both 'let' and 'var' properties and would allow a 
>> single memberwise initialization rule to be used for all properties.
>> 
>>> I feel like all these arguments could also be made for 'let'; what makes a 
>>> get-only var different from the initializer's perspective?
>> 
>> This is true in some sense.  The difference is that 'let' properties only 
>> have access control for a getter making it the only option we have if they 
>> are allowed to participate in memberwise initialization.  
> 
> That line of reasoning doesn't make sense. 'let' properties only have access 
> control for a getter because they never have a setter; the setter is 
> effectively always private.

Maybe I'm not communicating very clearly, of course that is the case.  But 
'let' properties should still be able to participate in memberwise 
initialization.  If we are going to apply access control rules (which I think 
is important if we allow the automatic model for property eligibility) we have 
to use the only access control setting available to them in the language as it 
exists.  

Allowing a distinct access control to be specified for initialization would 
solve this problem.  Adopting the opt-in model for property eligibility avoids 
the access control complications altogether.  I like that model quite a bit but 
Chris wanted to stick with the automatic model because it doesn't require a new 
declaration modifier on properties.

> 
>> Here's an example.  Think of a progress property.  That will be a far with a 
>> public getter but a private setter.  It would clearly be wrong if that were 
>> exposed by an initializer.  If we use the getter for a 'var' in memberwise 
>> initialization it would be exposed to all memberwise initializers under the 
>> current proposal (without any of the enhancements).  
> 
> What type would have a progress property *and* useful memberwise 
> initialization of its other state? In fact, what type has private state at 
> all and useful memberwise initialization of its public state? I'm having 
> trouble seeing these as realistic use cases, since as soon as you have some 
> form of state encapsulation you usually also want to curate the 
> initialization of that state. At that point, hiding the memberwise code 
> generation starts obscuring the logic rather than helping IMO, especially 
> since there's probably validation that should be interleaved with it.

I would have to think about the progress example longer than I have time at the 
moment to get specific.

UI widgets very commonly have private state and also many appearance attributes 
that are user configurable and great candidates for memberwise initialization.  
Many of them are likely to have 'public private(set) var' properties as well 
which should not be exposed to callers during initialization.

> 
> The rules you've proposed for what properties correspond to memberwise 
> parameters are already tricky. It would be a nice simplification to say that 
> all stored properties that need initialization end up in the memberwise 
> initializer, regardless of visibility.

That would severely cripple the feature IMO.  It would make it "all or nothing" 
and be useless in cases such as UI widgets where you need both private state 
and public state. 

It's common to just have callers set those attributes to desired values 
immediately after I initialization completes.  Many people write small helper 
libraries to make this less verbose, some of which have been discussed on this 
list.  This is a failure of the initialization capabilities of the language 
IMO.  This proposal is an attempt to make it easier to write types that can be 
fully configured during initialization.

The opt-in model avoids the complexity while retaining flexibility at the cost 
of requiring a declaration modifier in properties.  I think this is a very 
reasonable tradeoff to make and would be happy to support that approach as an 
alternative to or in addition to the "automatic" approach used in the current 
proposal.

Matthew

> 
> -Joe
> 
>> Types with properties like this are not uncommon.  Memberwise initialization 
>> would be useless with these types if the getter visibility was used.  
>> 
>> There are several ways to solve this but Chris did not want to include any 
>> of them in the initial proposal.  I went with what I feel is the least bad 
>> option remaining, which is to use the setter visibility for 'var' 
>> properties.  
>> 
>> It is least bad because it will actually be the right thing a lot of the 
>> time and because you can still use memberwise initialization for other 
>> properties when it doesn't do what you need.  Using the getter would be 
>> right some of the time (less often I think, but that's just a guess) but 
>> when it isn't you would have to avoid memberwise initialization for the 
>> entire type.
>> 
>> It is different than 'let' properties because it has to be if we want to do 
>> the least bad thing for 'var' properties and we also want to allow 'let' 
>> properties to participate in memberwise initialization.
>> 
>> Matthew
>> 
>>> 
>>> -Joe
> 
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to