<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 1, 2016, at 6:57 AM, Tino Heth <<a href="mailto:2th@gmx.de" class="">2th@gmx.de</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=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">I deny that, and even if it is true, there is a price to pay — and that is more than the lines of code that are required…</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Personally, I think it is a lot more readable to put members separate lines, but if you don’t like doing that:</div></div></div></div></blockquote><div class="">You are focusing on the least important thing here — I basically meant to say that the lower line count is no real benefit, but that there are advantages that aren't as easy to spot.</div></div></div></div></blockquote><div><br class=""></div><div>What are those advantages precisely? </div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class="">1. It interacts well with access control</div></blockquote><div class="">Better than Kotlin? Please prove this.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Please look at the examples I have in the Access Control section of the proposal. I spent some time reading the Kotlin docs and it isn’t clear to me that Kotlin can do this. But maybe it can. I don’t know Kotlin well. It sounds like you do, so if it can, please show how this is done in Kotlin.</div></div></div></div></blockquote><div class="">I actually don't know Kotlin that well — and that contributes to my evaluation of their solution: It is intuitive, and I did not have to read a huge article to understand it.</div><div class="">What I can see in your example is that the proposed syntax allows me to trigger compiler errors that will never happen with Kotlin (and errors that cannot happen are the ones I like the most).</div></div></div></div></blockquote><div><br class=""></div><div>Can you point out what potential compiler errors you are concerned about? Are you referring to the access control example where the compiler does not synthesize initialization of a private member in an internal memberwise initializer and thus requires manual initialization of the private member?</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class="">2. Partial memberwise initialization is possible</div></blockquote><div class="">The same with Kotlin — and imho at least as easy</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">That isn’t clear from the Kotlin docs. It may well be that they are just missing examples. Please post some samples showing how this is handled.</div></div></div></div></blockquote><div class="">see below; of course, the sample won't use memberwise initialization, but archive the same in a (imho) better way</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class="">3. It allows memberwise initializers to accept non-memberwise parameters to initialize private state</div></blockquote><div class="">I think this can be achieved with less effort using function-like class declaration (afair Joe already gave an example)</div></div></div></div></blockquote><div class=""><br class=""></div>I don’t see either of the examples Joe posted doing this. Here is an example showing what I mean:</div><div class=""><br class=""></div><div class=""><pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span style="color: rgb(51, 51, 51);" class=""><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">struct</span> S {
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> s: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">String</span>
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">private</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> i: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Int</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// user declares:</span>
memberwise <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</span>(other: S, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">...</span>) {
i <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">other.i</span>
}
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// compiler synthesizes (suppressing memberwise initialization for properties with lower visibility):</span>
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</span>(other: S, s: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">String</span>) {
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">/* synthesized */</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">self</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">.</span>s <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> s
<span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// body of the user's initializer remains</span>
i <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> </span><font color="#0086b3" class="">other.i</font><font color="#333333" class="">
}
}</font></pre></div></div></div></blockquote><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Instead of several examples, I'll use just a single one to illustrate a bunch of points — and I'm leaving out comments on purpose, because I hope to see others participating with their interpretation:</div><div class=""><br class=""></div><div class="">public class Customer(title: String, private var birthday: NSDate?, public address: String = "n/a"): Person {</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>protected let statusPoints = - birthday?.timeIntervalSinceNow() ?? 0.0</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let constantWithHardToExpressValue: Int</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>lazy var age: Int = dateCalculationIsHard(birthday)</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>init {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>constantWithHardToExpressValue = Int(statusPoints) + 1</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>super.init(title: title)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>public init(titlePrefix: String, titleSuffixObject: Any) {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>init(title: titlePrefix + titleSuffixObject.description, birthday: NSDate())</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div class="">}</div><div class=""><br class=""></div><div class="">So: Dear reader, please do my job and explain the "pseudo"-source above ;-) — or ask questions if you are just puzzled by it.</div></div></div></div></blockquote><div><br class=""></div><div>This must be what you are suggesting for Swift because the example uses NSDate? Thank you for providing a concrete example to look at.</div><div><br class=""></div><div>Is it correct that this class would have the following members in addition to the ones declared in the body? You used access control modifiers in that parameter list. Would you allow any annotations that are valid for properties that can be initialized (i.e. not lazy, but maybe an observable behavior if Property Behaviors are accepted)?</div><div><br class=""></div><div>let title: String // internal</div><div>private var birthday: NSDate?</div><div>public let address: String = “n/a”</div><div><br class=""></div><div>It actually looks like you pass `title` to super so maybe that isn’t expected to synthesize a member? If that is the case how does the compiler determine which parameters should receive member synthesis? If not, I assume super would not have a `title` member and is doing something else with that argument. Is that what you intend?</div><div><br class=""></div><div>Is it also correct that all of the following forms would be valid at call sites?</div><div><br class=""></div><div>Customer(title: “a title”, birthday: nil)</div><div>Customer(title: “a title”, birthday: nil, address: “an address”)</div><div>Customer(titlePrefix: “a prefix”, titleSuffixObject: Foo())</div><div><br class=""></div><div>If so, does the initializer used in the first two call examples (the designated / memberwise initializer?) receive the same access control as the type itself since it cannot be specified directly?</div><div><br class=""></div><div>Is it also correct that the init block that calls super would be invoked regardless of which initializer form is used? When would this block run? Immediately after the memberwise initializer is called? Is it the “body” of the memberwise initializer? It would need to run prior to any use of self in the body of `public init(titlePrefix: String, titleSuffixObject: Any)` in order to follow Swift's rules of definitive initialization. </div><div><br class=""></div><div>Is the `public init(titlePrefix: String, titleSuffixObject: Any)` initializer actually a convenience initializer? Is it required to call the designated / memberwise initializer before it does anything else? What rules need to be followed to ensure definitive initialization happens? Is this rule applicable to <b class="">all</b> additional initializers the author writes? If it is a convenience initializer maybe it just follows the current rules for those in Swift?</div><div><br class=""></div><div>Maybe the memberwise parameters plus the body is the single and only designated initializer for the type? Is that what you’re suggesting? What if the init body needs additional non-memberwise parameters? Is it allowed to specify those? If so how is that accomplished? How is the parameter ordering in the final parameter list determined? Would you use the `…` placeholder for the memberwise parameters like the current proposal does?</div><div><br class=""></div><div>What happens if another initializer wants to initialize `constantWithHardToExpressValue` to a value different than that in the factored out init block? </div><div><br class=""></div><div>What if the type needs to support more than one designated initializer? Is that possible? Would all designated initializers be required to receive the same set of memberwise parameters? If that isn’t what is required how would the author implement the necessary initializers?</div><div><br class=""></div><div>There a lot of details to work through here. If we are do that we would could analyze the differences of the two approaches. I think that is a fair request. There are definitely some significant differences between them. I will hold off on commenting further until we nail down exactly what it is you would like to see and how it would work.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class="">4. More than one memberwise initializer is possible</div></blockquote><div class="">Kotlin has no need for memberwise initializers at all, and I see this as a big advantage</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Please explain how it is an advantage. How does Kotlin handle a case where you have some private state that needs to be initialized internally to protect invariants, but also some members which users can initialize (such as appearance attributes on a UI widget)?</div></div></div></div></blockquote><div class="">For me, something that is not necessary is always an advantage — because you can simply remove it and have a result that is more elegant and compact.</div><div class="">Why would you want to add a feature that is not needed? It's just more work for those who actually build it, and it's more work for those who have to learn how to use it.</div></div></div></div></blockquote><div><br class=""></div><div>I don’t understand how this is a response to my question. It is very common for a UI widget to have both internal state that is necessary to its implementation but not visible to users, as well as appearance properties that are directly configurable by its users. In any case, lets focus on the previous example you gave as I believe it will address the question.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">5. Memberwise initialization of properties with declaration modifiers, behaviors / delegates is possible</div></blockquote><div class=""><a href="https://kotlinlang.org/docs/reference/delegated-properties.html" class="">https://kotlinlang.org/docs/reference/delegated-properties.html</a></div><div class="">(afaik this is not only possible, it's handled by the current compiler for a long time)</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Yes, I know Kotlin has this feature. It isn’t clear from the docs how initialization of such properties is handled (for example an Observable property). Maybe you can provide some examples of how this works.</div></div></div></div></blockquote><div class="">No, I can't (well, I accidentally did it partly...) — but I don't see why I should prove the features of a system that actually exists (and where everyone can easily check the behavior):</div><div class="">I think it's not that presumptuous to assume that the Kotlin-compiler has no flaws which are so fundamental.</div></div></div></div></blockquote><div><br class=""></div><div>You are suggesting a design we should use for a feature in Swift. I don’t think it is unreasonable to ask how that design would address specific use cases in Swift. It is not enough to point at another language with a similar feature. It is also not enough to just assume the Kotlin model is acceptable without being able to answer how it works in specific use cases.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><div class="">Afaics there not much room left for the promised additional flexibility… and the problem with default values for constants just doesn't exist in Kotlin at all.</div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">This is currently a problem in Swift. I am confident that it can be solved one way or another. I don’t think a solution should be tied to the “type initializer parameter list” syntax.</div></div></div></div></blockquote><div class="">As I said before:</div><div class="">There is no need to copy, but there is also no need to discard a working solution without further explanation.</div></div></div></div></blockquote><div><br class=""></div><div>I am taking a nontrivial amount of time to work through this with you and am keeping an open mind during that discussion, but it will require specific details to change my mind. Lets focus on the example you gave and get the details of what you want to see worked out. </div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">If you can clearly demonstrate how Kotlin is superior in a specific area I will give that great consideration. I want this proposal to be the best it can be. However, you’re going to need to do more than just link to the docs which I have already looked at.</div></div></div></div></blockquote><div class="">I see it from the other direction:</div><div class="">You have a "theory" (the proposal) and claim it is sound; Kotlin, on the other hand, is real working code!</div></div></div></div></blockquote><div><br class=""></div><div>I am trying to solve a problem for Swift. I am willing to continue working through the Kotlin approach with you so we can understand the details of how it would fit in with Swift. That will allow a fair comparison of the differences between the approaches.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">The good news is that as far as I can tell the things you like about what Kotlin is doing are not mutually exclusive with this proposal at all. Think of it this way - this proposal provides a flexible and orthogonal foundation for memberwise initialization. If desired, a future enhancement could easily be developed to provide additional syntactic sugar on top of it. The example Joe posted shows how that might work. </div><div class=""><br class=""></div><div class="">If this proposal is accepted and you want to pursue a proposal for that additional layer of syntactic sugar to get closer to Kotlin syntax I encourage you to do that. The new syntax should be evaluated independently as its own proposal. I would be happy to help show how your desired syntax could be transformed into existing syntax (including the memberwise initialization syntax if this proposal is accepted).</div></div></div></div></blockquote>I guess you really want to see your proposals accepted — and I understand that, as I'm quite sure that you put a huge amount of work into them.</div></div></div></blockquote><div><br class=""></div><div>I want to see the problems solved in the best way possible. That is why I am investing time in the proposals and also why I am investing time in exploring the alternative you believe is better. If there is a better approach or a way to improve my proposal I would prefer to identify that now rather than have it accepted as-is.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">But a "let's just take my solution and maybe integrate yours laterl"-attitude imho is not the right way:</div><div class="">If it is used to silence opposers without actually supporting them later, it is wily; and if it is a honest offer, we'll end up with a language that is extrem complicated because it tries to please everyone (and orthogonality would suffer as well).</div></div></div></blockquote><div><br class=""></div><div>I was trying to show that the two features are not strictly mutually exclusive as one can be expressed in terms of the other. If you don’t like that approach and think it makes the language too complex I understand that position. I am definitely not trying to just silence you. </div><div><br class=""></div><div>Let’s work together to understand in detail the differences in these approaches and their respective advantages and disadvantages. The first step in doing that is getting the design of what you would like to see nailed down further.</div></div><br class=""><div class="">Matthew</div></body></html>