<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 &lt;<a href="mailto:2th@gmx.de" class="">2th@gmx.de</a>&gt; 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? &nbsp;</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. &nbsp;I spent some time reading the Kotlin docs and it isn’t clear to me that Kotlin can do this. &nbsp;But maybe it can. &nbsp;I don’t know Kotlin well. &nbsp;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? &nbsp;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. &nbsp;It may well be that they are just missing examples. &nbsp;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. &nbsp;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:&nbsp;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&nbsp;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? &nbsp;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? &nbsp;You used access control modifiers in that parameter list. &nbsp;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? &nbsp;If that is the case how does the compiler determine which parameters should receive member synthesis? &nbsp;If not, I assume super would not have a `title` member and is doing something else with that argument. &nbsp;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? &nbsp;When would this block run? &nbsp; &nbsp; Immediately after the memberwise initializer is called? &nbsp;Is it the “body” of the memberwise initializer? &nbsp;It would need to run prior to any use of self in the body of `public&nbsp;init(titlePrefix: String, titleSuffixObject: Any)` in order to follow Swift's rules of definitive initialization. &nbsp;</div><div><br class=""></div><div>Is the `public&nbsp;init(titlePrefix: String, titleSuffixObject: Any)` initializer actually a convenience initializer? &nbsp;Is it required to call the designated / memberwise initializer before it does anything else? &nbsp;What rules need to be followed to ensure definitive initialization happens? &nbsp;Is this rule applicable to <b class="">all</b>&nbsp;additional initializers the author writes? &nbsp;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? &nbsp;Is that what you’re suggesting? &nbsp;What if the init body needs additional non-memberwise parameters? &nbsp;Is it allowed to specify those? &nbsp;If so how is that accomplished? &nbsp;How is the parameter ordering in the final parameter list determined? &nbsp;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? &nbsp;</div><div><br class=""></div><div>What if the type needs to support more than one designated initializer? &nbsp;Is that possible? &nbsp;Would all designated initializers be required to receive the same set of memberwise parameters? &nbsp;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. &nbsp;If we are do that we would could analyze the differences of the two approaches. &nbsp;I think that is a fair request. &nbsp;There are definitely some significant differences between them. &nbsp;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. &nbsp;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. &nbsp;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. &nbsp;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. &nbsp;It isn’t clear from the docs how initialization of such properties is handled (for example an Observable property). &nbsp;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. &nbsp;I don’t think it is unreasonable to ask how that design would address specific use cases in Swift. &nbsp;It is not enough to point at another language with a similar feature. &nbsp;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. &nbsp;I am confident that it can be solved one way or another. &nbsp;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. &nbsp;Lets focus on the example you gave and get the details of what you want to see worked out. &nbsp;</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. &nbsp;I want this proposal to be the best it can be. &nbsp;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. &nbsp;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. &nbsp;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. &nbsp;Think of it this way - this proposal provides a flexible and orthogonal foundation for memberwise initialization. &nbsp;If desired, a future enhancement could easily be developed to provide additional syntactic sugar on top of it. &nbsp;The example Joe posted shows how that might work. &nbsp;</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. &nbsp;The new syntax should be evaluated independently as its own proposal. &nbsp;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. &nbsp;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. &nbsp;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. &nbsp;If you don’t like that approach and think it makes the language too complex I understand that position. &nbsp;I am definitely not trying to just silence you. &nbsp;</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. &nbsp;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>