<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 7, 2016, at 8:30 PM, Joe Groff <<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jan 7, 2016, at 11:30 AM, Matthew Johnson <<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jan 7, 2016, at 12:51 PM, Joe Groff <<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jan 7, 2016, at 10:49 AM, Matthew Johnson <<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class=""><br class="Apple-interchange-newline">On Jan 7, 2016, at 12:37 PM, Joe Groff <<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jan 7, 2016, at 10:32 AM, David Owens II <<a href="mailto:david@owensd.io" class="">david@owensd.io</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">And this is more clear than this?</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><font face="Menlo" class=""><br class=""></font></div><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><font face="Menlo" class="">class Foo {<br class=""></font><font face="Menlo" class=""> var x,y,z: Int<br class=""></font><font face="Menlo" class=""> init(x: Int, y: Int, z: Int) {</font></blockquote><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><font face="Menlo" class=""> self.x = x</font></blockquote><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><font face="Menlo" class=""> self.y = y</font></blockquote><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><font face="Menlo" class=""> self.z = z</font></blockquote><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><font face="Menlo" class=""> }</font></blockquote><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><font face="Menlo" class="">}</font></blockquote></div></blockquote></div><br class=""><div class="">No, it isn't, but Matthew asked… I'm personally not too motivated to support anything more than all-or-nothing memberwise initialization, and tend to agree that anything more specialized deserves an explicit implementation.</div></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Maybe you would feel differently if you were an app developer. Different kinds of code have different needs. The most important use cases I have in mind are related to UI code, which is often the majority of the code in an app.</div></div></blockquote><br class=""></div><div class="">Do you have any concrete examples in mind?</div><div class=""><br class=""></div><div class="">-Joe</div><br class=""></div></div></blockquote><br class=""></div><div class="">Here is an example where partial memberwise initialization would apply. It is similar to something in a real project:</div><div class=""><br class=""></div><div class="">public class FontPicker: UIControl {</div><div class=""> public let fonts: [UIFont]</div><div class=""><br class=""></div><div class=""> public var fontSize: CGFloat = 22</div><div class=""> public var foregroundColor: UIColor = UIColor.darkGrayColor()</div><div class=""> public var backgroundColor: UIColor = UIColor.whiteColor()</div><div class=""> // A bunch of other appearance attributes here</div><div class=""><br class=""></div><div class=""> private let collectionView: UICollectionView</div><div class=""> private let layout: UICollectionViewLayout</div><div class=""> // other internal state required by the implementation</div><div class=""><br class=""></div><div class=""> public memberwise init(...) {</div><div class=""> // configure the collection view and add it as a subview</div><div class=""> }</div><div class="">}</div><div class=""><br class=""></div><div class="">A couple points are relevant here:</div><div class=""><br class=""></div><div class="">1. Memberwise initialization is very valuable for the appearance attributes, but is useless if it exposes our implementation details.</div><div class=""><br class=""></div><div class="">2. In many custom UI widgets the appearance attributes don’t really need to be mutable post-initialization. At the same time, it is necessary to allow, but not require a value to be specified. It would be ideal if they were `let` properties with a default value, but still able to participate in memberwise initialization. Without that capability we are forced to choose between the advantages of using a `let` property and the advantages of memberwise initialization.</div><br class=""><div class="">UI widgets are a great example. View controllers often have a similar divide between state provided by the user and state related to internal implementation details.</div></div></div></blockquote><br class=""></div><div class="">Access control seems like a poor tool for the kind of categorization you want here. The vast majority of code is app code, where there's no reason to use 'public', so 'internal' and 'private' are the interesting visibility layers. Using 'private' to opt fields out of memberwise initialization is too brittle, in my opinion—You've made it much harder to factor the class's functionality into different files in the future, since you can no longer change any of these fields to internal without also breaking all of the memberwise initializers as a second-order effect.</div></div></div></blockquote><div><br class=""></div><div>One thing I should have mentioned in the reply last night is that the problem of breaking the memberwise initializers when access control changes is solvable. Several of the possible enhancements are attempts to allow the programmer to be more explicit when the rules don’t do the right thing. The breakage you describe is an example where that would be necessary.</div><div><br class=""></div><div>The solution I believe is the best one (assuming the automatic model) is allowing distinct access control for initialization. Initialization is conceptually distinct from both getting and setting. We already allow programmers to specify distinct access levels for `get` and `set` (for `var`), but we don’t for `init`. It feels like a natural extension of the access control model to allow a distinction for initialization. The `init` access level could also be used in phase 1 for manually written initializers, rather than the `get` visibility of a `let` property and the `set` visibility of a `var` that is used today.</div><div><br class=""></div><div>It would solve the problem problem you mention above by allowing the access control to be specified as `internal private(init)` rather than just `internal`. This access control change would have no impact on memberwise initializers.</div><div><br class=""></div><div>This would also solve the problem you mentioned earlier that `let` properties more capable than `private(set) var` properties. It would no longer be necessary to use the `set` access level because there would be a distinct access level for `init`. In that case, the programmer could specify exactly what is desired: </div><div><br class=""></div><div>1. `public private(set)` would allow public memberwise initializers to synthesize a parameter for the property</div><div>2. `private public(get)` would only allow private memberwise initializers to synthesize a parameter for the property. Only the getter would be visible publicly.</div><div>3. `public private(init)` would only allow private memberwise initializers to synthesize a parameter for the property. Both the getter and setter would be visible publicly.</div><div><br class=""></div><div>Ultimately, I think the automatic model is only a good idea if we enforce access control. Allowing the distinction to be made solves the problems you have pointed out while also allowing the programmer to get the desired behavior out of the automatic model in most or all cases. For those reasons I think it would be a significant improvement over the current proposal.</div><div><br class=""></div><div>Matthew</div></div></body></html>