<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 Dec 21, 2015, at 7:47 PM, Chris Lattner &lt;<a href="mailto:clattner@apple.com" class="">clattner@apple.com</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="">On Dec 21, 2015, at 11:32 AM, Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<div class=""><blockquote type="cite" class=""><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="">I have completed a draft of the proposal I have been working on for flexible memberwise initialization. &nbsp;I am really looking forward to your input and will be refining the proposal based on our discussion.<div class=""><br class=""></div><div class="">I am including a current snapshot of the proposal in this message. &nbsp;I will keep the proposal up to date on Github at this link:</div><div class=""><br class=""></div><div class=""><a href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md" class="">https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md</a></div></div></div></blockquote><div class=""><br class=""></div><div class="">This is a really really interesting approach, I really like it. &nbsp;Detailed comments below, I’m skipping all the stuff I agree with or have no additional comments on:</div></div></div></div></blockquote><div><br class=""></div><div>Hi Chris, thanks! &nbsp;I’m really excited to hear that you like it!</div><div><br class=""></div><div>Replies to your comments are inline. &nbsp;I hope you’re willing to entertain on some discussion on some aspects of the proposal that you are not immediately sold on. &nbsp;:) &nbsp;I am hoping we can find a way to address the goals they represent even if the eventual solution looks different than the current one.</div><div><br class=""></div><div>The examples are definitely not a complete representation of what is described in the detailed design. &nbsp;I assume they provided sufficient context for your initial feedback. &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 style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; line-height: 1.2; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255); margin-top: 0px !important;" class="">Flexible Memberwise Initialization</h1><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class=""><a id="user-content-replacing-the-current-memberwise-initializer" class="anchor" href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#replacing-the-current-memberwise-initializer" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><span class="octicon octicon-link" style="box-sizing: border-box; font-weight: normal; font-size: 16px; line-height: 1; font-family: octicons; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased; -webkit-user-select: none; vertical-align: middle; visibility: hidden;"></span></a>Replacing the current memberwise initializer</h3><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);"><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 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);">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>() {}
</pre></div></div></div></blockquote><div class="">It never occurred to me to allow a body on a memberwise initializer, but you’re right, this is a great feature. &nbsp;I love how this makes memberwise init behavior a modifier on existing initializers.</div></div></div></div></blockquote><div><br class=""></div>Yep, the basis of the idea is that the initializer itself handles any non-trivial work and allows the compiler to generate the trivial boilerplate. &nbsp;The “flexibile” aspect of the idea is that the type / initializer author has enough control to tell the compiler what is trivial and what is not in a relatively concise manner.<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 style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class="">Properties with initial values</h3><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);"><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 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);">=</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>hello<span class="pl-pds" style="box-sizing: border-box;">"</span></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-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);">42</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>() {}
    <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// compiler synthesizes:</span>
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</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);">=</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>hello<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, i: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Int</span> <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);">42</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-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>i <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> i
    }
}</pre></div></div></div></blockquote><div class="">In the case of let properties, I’m uncomfortable with this behavior and it contradicts our current init rules (the synthesized code isn’t legal). &nbsp;Please change the example to var properties, and then it’s can fit with the model :-). &nbsp;</div></div></div></div></blockquote><div><br class=""></div><div>I understand that this is not legal under the current init rules because the compiler currently produces a synthesized initialization of the properties to their initial values at the beginning of the initializer. &nbsp;I actually don’t like this behavior because it doesn’t allow an initializer body to initialize a let property with an "initial value”. &nbsp;</div><div><br class=""></div><div>I’m pretty sure I’m not alone in this. &nbsp;People want to use immutable properties with “default values” (I believe this is what most Swift developers are calling what the Swift team refers to as “initial values”) without a requirement that all instances actually have that value. &nbsp;It was actually pretty surprising to me, and I’m sure to others as well, to discover this limitation. &nbsp;I actually thought it was a limitation of the current implementation rather than something that was intentionally designed. &nbsp;I’m surprised to hear otherwise.</div><div><br class=""></div><div>IMO it makes more sense that the “initial value” is a default and is only used when necessary - i.e. when the initializer body does not initialize the property directly. &nbsp;This does not contradict immutability of the property for instances of the type as it is still initialized and never modified afterwards. &nbsp;If we don’t allow initializers to provide a different value than the “initial value” default and we have a type where that is necessary for some initializers we are forced to omit the “initial value” and duplicate it in all of the initializers that actually need it (either as a parameter default value or as part of a property initialization statement in the body of the initializer). &nbsp;This seems inflexible and results in duplicated constants in our code which is never a good thing.</div><div><br class=""></div><div>The proposal as written includes as part of the synthesis algorithm a modification to the current behavior so that initial value synthesis only happens if a member is not assigned in the post-synthesis initializer body. &nbsp;It also includes an aside which recommends making this change to the initialization rules applicable to all initializers, not just memberwise initializers. &nbsp;I consider this to be an improvement that falls in the general category of “flexible initialization”, memberwise or not.</div><div><br class=""></div><div>With the modified initialization rules covered in the proposal the synthesized code in the example would be legal.</div><div><br class=""></div><div>If you’re still uncomfortable with this behavior and with a change to the init rules allowing initializers to initialize let properties with a value different than the “initial value” specified in the declaration can you elaborate on the rationale? &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=""><div class=""><br class=""></div><div class="">That said, I think the interaction of explicit initializers and memberwise initializers begs discussion. &nbsp;It would be a much simpler model to only get memberwise parameters for properties without an explicit init. &nbsp;Have you considered this model, what are the tradeoffs with allowing vars to overwrite them? &nbsp;Allowing an explicit init to be overwritten by the memberwise initializer seems potentially really confusing, and since you allow explicit arguments on inits, this could always be handled manually if someone really really wanted it. &nbsp;For example, they could write:</div><div class=""><br class=""></div><div class="">memberwise init(s : String) {</div><div class="">&nbsp; self.s = s</div><div class="">}</div><div class=""><br class=""></div><div class="">If they wanted to get the sugar of memberwise inits (presumably for other properties without an explicit init) but still allow one to be overwritten.</div></div></div></div></blockquote><div><br class=""></div><div>Personally, I think there is a lot of value in allowing memberwise initialization for properties that do contain an initial value. &nbsp;Imagine a hypothetical Swift version of Cocoa Touch. &nbsp;UILabel might have initial values for text, font, textColor, etc but still want to allow clients to provide memberwise initialization arguments to override the default value. &nbsp;I think there are many cases like this both in UI code and elsewhere. &nbsp;</div><div><br class=""></div><div>I think the complexity of the model stems from the fact that initialization itself can be rather complex. &nbsp;It is essential rather than incidental complexity and it must be dealt with somehow - either through boilerplate, through compiler synthesis, through restrictions on desired flexibility, or through punting and requiring users to overwrite default values with assignment after initialization completes. &nbsp;Obviously this proposal goes pretty far down the path of synthesis.</div><div><br class=""></div><div>It is very reasonable to have a discussion about what the right tradeoffs are here. &nbsp;My hope is that we can achieve flexibility without boilerplate and without causing confusion whenever that is possible. &nbsp;</div><div><br class=""></div><div>I’m definitely interested in hearing more thoughts on this. &nbsp;What do you think the downsides are of synthesizing memberwise initialization for properties with an “initial value”? &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=""><div class=""><br class=""></div><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class=""><a id="user-content-partial-memberwise-initialization" class="anchor" href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#partial-memberwise-initialization" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><span class="octicon octicon-link" style="box-sizing: border-box; font-weight: normal; font-size: 16px; line-height: 1; font-family: octicons; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased; -webkit-user-select: none; vertical-align: middle; visibility: hidden;"></span></a>Partial memberwise initialization</h3><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);"><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 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);">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>() {
        i <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> getTheValueForI()
    }
    <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// compiler synthesizes (suppressing memberwise initialization for properties assigned in the initializer body):</span>
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</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);">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> getTheValueForI()
    }
}</pre></div></div></div></blockquote><div class="">This doesn’t seem like the right behavior to me. &nbsp;The compiler shouldn’t be in the business of scanning the body of the init to decide what members are explicitly initialized. &nbsp;I’d suggest that the model simply be that the contents of the {} on a memberwise init get injected right after the memberwise initializations that are done. &nbsp;This mirrors how properties with default values work.</div></div></div></div></blockquote><div><br class=""></div><div>The model does inject the synthesized memberwise initialization just prior to the body of the initializer. &nbsp;</div><div><br class=""></div><div>As written the proposal does scan the body of the init in order to determine which properties receive memberwise initialization. &nbsp;The idea here is that it provides additional flexibility as it allows specific initializers to “opt-out” of memberwise initialization synthesis for some properties while receiving it for others.</div><div><br class=""></div><div>One alternative to this I think I forgot to include in the alternatives section is to allow the `memberwise` declaration modifier on the initializer to be annotated in some way that prevents memberwise initialization synthesis of some parameters that would otherwise receive it. &nbsp;What do you think of this approach? &nbsp;It certainly runs in the direction of Swift’s emphasis on clarity. &nbsp;</div><div><br class=""></div><div>If you like this approach better do you have any ideas on what the syntax might look like? &nbsp;I think it would be best to provide a list of properties omitted from memberwise init synthesis rather than an opt-in list as that would likely be the shorter list. &nbsp;I don’t have any great ideas for syntax though.</div><div><br class=""></div><div>IMO an important aspect of the “flexible” part of this proposal is that it allows specific initializers to "take control” of initialization of specific properties that may be memberwise intialized by most initializers, while still receiving memberwise initialization of other properties.</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=""><div class=""><br class=""></div><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class=""><a id="user-content-lazy-properties-and-incompatible-behaviors" class="anchor" href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#lazy-properties-and-incompatible-behaviors" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><span class="octicon octicon-link" style="box-sizing: border-box; font-weight: normal; font-size: 16px; line-height: 1; font-family: octicons; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased; -webkit-user-select: none; vertical-align: middle; visibility: hidden;"></span></a>lazy properties and incompatible behaviors</h3><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);"><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 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);">lazy</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> i: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Int</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> InitialValueForI()

    <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>() {
    }
    <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// compiler synthesizes:</span>
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</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);">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);">// compiler does not synthesize initialization for i </span>
        <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// because it contains a behavior that is incompatible with </span>
        <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// memberwise initialization</span>
    }
}</pre></div></div></div></blockquote><div class="">Yes, this is likely to be subsumed into JoeG’s "behaviors” proposal. &nbsp;In the meantime, I’d suggest no behavior change for lazy properties.</div></div></div></div></blockquote><div><br class=""></div>I don’t think the proposal changes lazy properties. &nbsp;If it does that was not the intent so please point out how and where and I will make a change.</div><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=""><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class=""><a id="user-content-nomemberwise-properties" class="anchor" href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#nomemberwise-properties" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><span class="octicon octicon-link" style="box-sizing: border-box; font-weight: normal; font-size: 16px; line-height: 1; font-family: octicons; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased; -webkit-user-select: none; vertical-align: middle; visibility: hidden;"></span></a>@nomemberwise properties</h3><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);"><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 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);">@nomemberwise</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>(configuration: SomeTypeWithAnIntMember) {
        i <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> configuration<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">.</span>intMember
    }
    <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// compiler synthesizes:</span>
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</span>(configuration: SomeTypeWithAnIntMember, 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);">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
        i <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> configuration<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">.</span>intMember
    }
}</pre></div></div></div></blockquote><div class="">@nomemberwise is an interesting extension, but since it is a pure extension over the basic model, I’d suggest moving this into a “possible future extensions” section. &nbsp;The proposal doesn’t need this feature to stand on its own.&nbsp;</div></div></div></div></blockquote><div><br class=""></div><div>Allowing type authors to restrict memberwise initialization to a subset of properties is an important aspect of “flexible” memberwise initialization IMO. &nbsp;In my mind, this is about allowing the author of a type to segment properties that are “user configurable” from properties that are implementation details. &nbsp;</div><div><br class=""></div><div>Consider again the example of a Swift implementation of UI widget which would reasonably want to allow memberwise initialization of its appearance related properties but would also has a bunch of properties where memberwise initialization is not the right thing to do. &nbsp;Authors of the type need a way to prohibit memberwise initialization from happening. &nbsp;Lower access control would be sufficient to do this sometimes, but not always.</div><div><br class=""></div><div>If we include syntax allowing specific initializers to block memberwise initialization of specific properties (as mentioned previously) we could get away without @nomemberwise. &nbsp;However, that would cause many memberwise initializers that could otherwise avoid an opt-out list to include one. &nbsp;It would also be less clear because the real intention of the author is that the property should never participate in memberwise initialization at all.</div><div><br class=""></div><div>I hope this helps to explain why I consider it pretty important. &nbsp;I hope we can at least have a discussion about keeping it in the main body of the proposal.</div><div><br class=""></div><div>If you are strongly opposed to this I will of course move it.</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=""><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class=""><a id="user-content-delegating-and-convenience-initializers" class="anchor" href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#delegating-and-convenience-initializers" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><span class="octicon octicon-link" style="box-sizing: border-box; font-weight: normal; font-size: 16px; line-height: 1; font-family: octicons; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased; -webkit-user-select: none; vertical-align: middle; visibility: hidden;"></span></a>delegating and convenience initializers</h3><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);"><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 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);">=</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>hello<span class="pl-pds" style="box-sizing: border-box;">"</span></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-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);">42</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>() {}
    <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// compiler synthesizes:</span>
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</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);">=</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>hello<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, i: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Int</span> <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);">42</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-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>i <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> i
    }

    <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>(describable: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">CustomStringConvertible</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><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</span>(s: describable<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);">description</span>)
    }
    <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// compiler synthesizes (adding forwarded memberwise parameters):</span>
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</span>(describable: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">CustomStringConvertible</span>, i: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Int</span> <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);">42</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><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</span>(s: describable<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);">description</span>, i: i)
    }
}</pre></div></div></div></blockquote><div class="">This example is introducing two things: convenience inits, but also parameter arguments. &nbsp;For the sake of the proposal, I’d suggest splitting the parameter arguments out to its own discussion. &nbsp;It isn’t clear to me whether the memberwise initializers should come before explicit arguments or after, and it isn’t clear if we should require the developer to put something in the code to indicate that they exist. &nbsp;For example, I could imagine a syntax like this:</div><div class=""><br class=""></div><div class="">memberwise init(…) {} &nbsp;</div><div class="">memberwise&nbsp;init(describable:&nbsp;CustomStringConvertible, ...) {</div><div class=""><br class=""></div><div class="">Where the … serves as a reminder that the init takes a bunch of synthesized arguments as well.</div></div></div></div></blockquote><div><br class=""></div><div>The … placeholder is an interesting idea. &nbsp;I really like it. &nbsp;The algorithm in the current proposal always places the memberwise parameters at the end of the parameter list, but just prior to a trailing closure argument if one exists. &nbsp;This would allow additional flexibility of placement.</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=""><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class=""><a id="user-content-subclass-initializers" class="anchor" href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#subclass-initializers" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><span class="octicon octicon-link" style="box-sizing: border-box; font-weight: normal; font-size: 16px; line-height: 1; font-family: octicons; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased; -webkit-user-select: none; vertical-align: middle; visibility: hidden;"></span></a>subclass initializers</h3><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);"><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 class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">class</span> Base {
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> baseProperty: <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);">// user declares:</span>
    memberwise <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</span>() {}
    <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// compiler synthesizes:</span>
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</span>(baseProperty: <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);">self</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">.</span>baseProperty <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> baseProperty
    }
}

<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">class</span> Derived: Base {
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> derivedProperty: <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>() {}
    <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// compiler synthesizes (adding forwarded memberwise parameters):</span>
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</span>(baseProperty: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">String</span>, derivedProperty: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Int</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>derivedProperry <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> derivedProperty
        <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">super</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">.</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">init</span>(baseProperty: baseProperty)
    }
}
</pre></div></div></div></blockquote><div class="">This also seems unclear to me. &nbsp;We’re generally very concerned about tightly coupling derived classes to their bases (in an API evolution scenario, the two classes may be in different modules owned by different clients). &nbsp;Further, the base class may have multiple inits, and it wouldn’t be clear which one to get the arguments from.</div></div></div></div></blockquote><div><br class=""></div><div>I know there are a lot of complexities here. &nbsp;It is certainly possible I am missing some showstoppers, especially related to resilience, etc.</div><div><br class=""></div><div>User code would of course need to provide sufficient parameters to disambiguate the call to the base class initializer.</div><div><br class=""></div><div>The goal in this section is to enable memberwise initialization to be used in a class hierarchy. &nbsp;I think UIKit is a good case to consider for the sake of discussion. &nbsp;In a hypothetical Swift version of UIKit we would want to allow memberwise initialization of appearance attributes regardless of where they are declared in the class hierarchy. &nbsp;(I would hope a designed-for-Swift UIKit would not rely so heavily on inheritance, but nevertheless I think it makes good case study for discussing flexible memberwise initialization).</div><div><br class=""></div><div>The same mechanism that handles inheritance should also be able to handle delegating and convenience initializers. &nbsp;The idea is to write a delegating or convenience initializer that wraps the non-memberwise portion of a memberwise initializer while still allowing the memberwise initialization to “flow through” and be visible to callers of the delagating / convenience initializer.</div><div><br class=""></div><div>I attempted to outline a basic strategy for handling propagation of memeberwise initialization through the inheritance hierarchy as well as other cases of initializer delegation in the detailed design. &nbsp;It is definitely not complete, almost certainly has flaws and omissions, etc. &nbsp;I’m hoping we can flesh out the details through community discussion.</div><div><br class=""></div><div>I hope you will agree that it is important to support inheritable memberwise initialization and that we do need to address this in some 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=""><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class=""><a id="user-content-detailed-design" class="anchor" href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#detailed-design" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1;"><span class="octicon octicon-link" style="box-sizing: border-box; font-weight: normal; font-size: 16px; line-height: 1; font-family: octicons; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased; -webkit-user-select: none; vertical-align: middle; visibility: hidden;"></span></a>Detailed design</h2><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class=""><a id="user-content-syntax-changes" class="anchor" href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#syntax-changes" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><span class="octicon octicon-link" style="box-sizing: border-box; font-weight: normal; font-size: 16px; line-height: 1; font-family: octicons; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased; -webkit-user-select: none; vertical-align: middle; visibility: hidden;"></span></a>Syntax changes</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);" class="">This proposal introduces two new syntactic elements: the&nbsp;<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">memberwise</code>&nbsp;initializer declaration modifier and the&nbsp;<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">@nomemberwise</code>&nbsp;property attribute.</p></div></div></blockquote><div class="">As before, I’d suggest splitting&nbsp;@nomemberwise out to a “potential future extensions section”.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class=""><font size="4" class="">Al</font><span style="font-size: 1.5em;" class="">gorithm</span></h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);" class="">The steps described in this section will be followed by the compiler when it performs memberwise initialization synthesis. These steps supercede the synthesis of initialization for properties with initial values that exists today.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);" class="">When the compiler performs memberwise initialization synthesis it will determine the set of properties that are eligible for synthesis that&nbsp;<strong style="box-sizing: border-box;" class="">are not</strong>&nbsp;directly initialized in the body of the initializer. It will then synthesize parameters for them as well the initialization of them at the beginning of the initializer body.</p></div></div></blockquote><div class="">I’d strongly suggest considering a model where properties that have an explicit initializer don’t get a memberwise init.</div></div></div></div></blockquote><div><br class=""></div><div>You’ve said this a couple of times so I assume you have a pretty good reason for it. &nbsp;I’m not totally clear on the reason though, it simplifies the model. &nbsp;The current memberwise initializer supports var members with an initial value. &nbsp;Why do you think we should move away from supporting this? &nbsp;Can you elaborate further?</div><div><br class=""></div><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=""><br class=""></div><div class="">Have you considered whether computed properties make sense to loop into your model?</div></div></div></div></blockquote><div><br class=""></div><div>I’m not sure how a property that isn’t stored would be involved in initialization, memberwise or not. &nbsp;Am I missing something here?</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=""><div class=""><br class=""></div><div class="">Typo "initialzier”.</div></div></div></div></blockquote><div><br class=""></div>Thanks!</div><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 style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><ol style="box-sizing: border-box; padding: 0px 0px 0px 2em; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);" class=""><li style="box-sizing: border-box;" class=""><div style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><br class="webkit-block-placeholder"></div></li></ol><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class=""><a id="user-content-objective-c-class-import" class="anchor" href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#objective-c-class-import" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><span class="octicon octicon-link" style="box-sizing: border-box; font-weight: normal; font-size: 16px; line-height: 1; font-family: octicons; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased; -webkit-user-select: none; vertical-align: middle; visibility: hidden;"></span></a>Objective-C Class Import</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);" class="">Objective-C frameworks are extremely important to (most) Swift developers. In order to provide the call-site advantages of flexible memberwise initialization to Swift code using Cocoa frameworks this proposal recommends introducing a&nbsp;<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">MEMBERWISE</code>&nbsp;attribute that can be applied to Objective-C properties and initializers.</p></div></div></blockquote><div class="">This is also an orthogonal extension on top of the base proposal. &nbsp;I’d suggest splitting it off to a “possible future extensions” section as well.</div></div></div></div></blockquote><div><br class=""></div><div>This makes sense. &nbsp;I will do this.</div><div><br class=""></div><div>The reason I included this section is that I think most developers would really like some syntactic sugar for configuring instances of Cocoa classes. &nbsp;Enabling them to work with memberwise initialization seems like a pretty natural way to do this. &nbsp;But you’re right, this could certainly be a future follow-on proposal once we hash out the details on the Swift side. &nbsp;</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=""><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; background-color: rgb(255, 255, 255);" class=""><a id="user-content-impact-on-existing-code" class="anchor" href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#impact-on-existing-code" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1;"><span class="octicon octicon-link" style="box-sizing: border-box; font-weight: normal; font-size: 16px; line-height: 1; font-family: octicons; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased; -webkit-user-select: none; vertical-align: middle; visibility: hidden;"></span></a>Impact on existing code</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);" class="">The changes described in this proposal are strictly additive and will have no impact on existing code.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 25px; background-color: rgb(255, 255, 255);" class="">One possible breaking change which may be desirable to include alongside this proposed solution is to elimintate the existing memberwise initializer for structs and require developers to specifically opt-in to its synthesis by writing&nbsp;<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">memberwise init() {}</code>. A mechanical transformation is possible to generate this declaration automatically if the existing memberwise initializer is removed.</p></div></div></blockquote><div class="">I think that that would be very interesting to discuss, but I lean towards keeping our existing model for synthesizing a memberwise init if there is no other init in a struct (and we should do it for classes as well). &nbsp;Requiring someone to write "memberwise init() {}” is just boilerplate, and producing it as “internal” avoids most of the problems from being something undesirable being generated. &nbsp;That said, I see the argument that being more explicit is good.</div></div></div></div></blockquote><div><br class=""></div><div>Yeah, I don’t have a strong opinion on this. &nbsp;I just wanted to point out that making it explicit wouldn’t be too burdensome and it would eliminate any “hidden” initializers.</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=""><div class=""><br class=""></div><div class="">Overall, I’m a huge fan of this proposal and the direction you’re going in.</div></div></div></div></blockquote><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=""><br class=""></div><div class="">-Chris</div></div><br class=""></div></div></blockquote></div><div class=""><br class=""></div><div class="">This is really great to hear! &nbsp;I’m looking forward to continued discussion and refinement.&nbsp;</div><div class=""><br class=""></div><div class="">Matthew</div></body></html>