The protocol extension does not have to be in the same module as the protocol itself. How will the compiler know what variables are set in the partial initializer when it is compiling the protocol or the struct?<br><div class="gmail_quote"><div dir="ltr">On Sun, Jun 25, 2017 at 15:13 Robert Bennett &lt;<a href="mailto:rltbennett@icloud.com">rltbennett@icloud.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">For a concrete type, a partial initializer is a function that:<div>Can set `let` instance variables</div><div>May not refer to `self` in an rvalue</div><div>Must set the same subset of instance variables regardless of the code path taken</div><div><br></div><div>For a protocol, a partial initializer is simply a function that sets *any* subset of the instance variables. A protocol could provide a default implementation of one. In order for this `let` proposal to work, though, if a `let` variable is set in the protocol extension’s implementation of a (full) initializer, the protocol would need to provide at least one partial initializer that it does not provide an implementation for, so that a conforming type can fill in the gaps for all of the instance variables it defines that the protocol doesn’t require/know about. That way the compiler can have faith that a conforming type will be able to fully initialize itself with the default implementation of the required full initializer.</div></div><div style="word-wrap:break-word"><div><br><div><br><div><blockquote type="cite"><div>On Jun 25, 2017, at 3:57 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="m_-2343647433740274917Apple-interchange-newline"><div>So your proposed definition of a partial initializer is one that does not set any protocol requirement?<br><div class="gmail_quote"><div dir="ltr">On Sun, Jun 25, 2017 at 14:54 Robert Bennett &lt;<a href="mailto:rltbennett@icloud.com" target="_blank">rltbennett@icloud.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><div></div><div>The compiler would only raise an error when a conforming type violated the requirement that the partial initializer not set x. The protocol itself would never fail to compile.</div></div><div dir="auto"><div><br>On Jun 25, 2017, at 3:33 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr">On Sun, Jun 25, 2017 at 2:24 PM, Robert Bennett via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">You’re right Xiaodi, I did not entirely think this through. However I think this could still work with another addition to the language: partial initializers. These would be treated as initializers are now (meaning, for instance, no reference to self until initialization is complete) except they would only need to initialize a subset of the instance variables before exiting. An initializer could then satisfy the requirement that all instance variables must be initialized by calling partial initializers.<br>
<br>
By incorporating partial initializers, it would be possible to guarantee that a `let` variable in a protocol is only set once. This is because an init implemented in a protocol extension could delegate to a partial initializers required by the protocol, and because they are only partial initializers, they need not set the instance variables already set in the initializer; it would be up to a conforming type to ensure this is the caee. A confirming type would define the partial initializer to set everything not already set in the protocol extension’s init, and it would be a compiler error to set a variable in the partial initializer that is already set in the extension’s init without overriding the extension’s init.</blockquote><div><br></div><div>How can the compiler raise this error when the implementation of the partial initializer does not even have to exist at compile time?</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Example code:<br>
<br>
protocol P {<br>
    var x: Int { let } // or { get set(init) }, or whatever<br>
<br>
    partialinit initializeRest()<br>
    init()<br>
}<br>
<br>
extension P {<br>
    init() {<br>
        initializeRest()<br></blockquote><div><br></div><div>How can the compiler ensure that `initializeRest()` does not already set `x`?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
        self.x = 1<br>
<span>    }<br>
}<br>
<br>
struct S: P {<br>
    let x: Int<br>
</span>    var y: String<br>
<br>
    // It would be a compiler error to set x here without also redefining init()<br>
    partialinit initializeRest() {<br>
        self.y = “P has no knowledge of me”<br>
    }<br>
<br>
    // Can use default init provided by P<br>
<div class="m_-2343647433740274917m_8744431084820982882HOEnZb"><div class="m_-2343647433740274917m_8744431084820982882h5">}<br>
<br>
&gt; On Jun 23, 2017, at 8:12 PM, Karl Wagner &lt;<a href="mailto:razielim@gmail.com" target="_blank">razielim@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt; What you want is some way to guarantee value semantics when writing generic code.<br>
&gt;<br>
&gt; It’s a known hole, and admittedly quite a big one. I hope that there will be time for core language improvements like this in Swift 5. Be sure to raise the issue again once planning for that starts!<br>
&gt;<br>
&gt; - Karl<br>
&gt;<br>
&gt;&gt; On 23. Jun 2017, at 23:43, Robert Bennett via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Hello Swift Evolution,<br>
&gt;&gt;<br>
&gt;&gt; I’m bumping into an annoying problem with protocols. In a class or struct it is common to have a `let` instance variable and assign it in `init`. Unfortunately there is no way to translate this into a protocol with init in an extension. If attempting to set the variable in init in an extension, it must be of type { get set }, which means it cannot be a `let` constant in the conforming type. AFAIK there is no way around this — if you want to set an instance variable in an initializer in a protocol extension, it must be marked as { get set }. The alternative is to write the initializer separately for each adopting type, but this violates DRY.<br>
&gt;&gt;<br>
&gt;&gt; Hence, I am proposing a third option to go along with `get` and `set` in a protocol. This would indicate that the variable can be a constant, but is settable in an initializer. In this case, the conforming type *must* use `let` to declare the variable.<br>
&gt;&gt;<br>
&gt;&gt; Option 1: the keyword `let`. If present, it would need to be the only thing in the curly brackets because it simultaneously implies `get` and not `set`.<br>
&gt;&gt;<br>
&gt;&gt; protocol P {<br>
&gt;&gt;   var x: Int { let }<br>
&gt;&gt;   init(_ x: Int)<br>
&gt;&gt;   func modifyX()<br>
&gt;&gt; }<br>
&gt;&gt; extension P {<br>
&gt;&gt;   init(_ x: Int) {<br>
&gt;&gt;       self.x = x // This is ok; would not be ok if x were marked { get }<br>
&gt;&gt;   }<br>
&gt;&gt;<br>
&gt;&gt;   func modifyX() {<br>
&gt;&gt;       self.x += 1 // Not allowed<br>
&gt;&gt;   }<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; struct S: P {<br>
&gt;&gt;   let x: Int // This is ok; would not be ok if x were marked { get set }<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; Option 2: `set(init)`. Can (and often will) coexist with `get`.<br>
&gt;&gt;<br>
&gt;&gt; protocol P {<br>
&gt;&gt;   var x: Int { get set(init) }<br>
&gt;&gt;   init(_ x: Int)<br>
&gt;&gt;   func modifyX()<br>
&gt;&gt; }<br>
&gt;&gt; extension P {<br>
&gt;&gt;   init(_ x: Int) {<br>
&gt;&gt;       self.x = x // This is ok; would not be ok if x were marked { get }<br>
&gt;&gt;   }<br>
&gt;&gt;<br>
&gt;&gt;   func modifyX() {<br>
&gt;&gt;       self.x += 1 // Not allowed<br>
&gt;&gt;   }<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; struct S: P {<br>
&gt;&gt;   let x: Int // This is ok; would not be ok if x were marked { get set }<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; I’d like to hear all of your thoughts on this.<br>
&gt;&gt;<br>
&gt;&gt; Best,<br>
&gt;&gt; Robert<br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; swift-evolution mailing list<br>
&gt;&gt; <a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
&gt;&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;<br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</div></div></blockquote></div><br></div></div>
</div></blockquote></div></blockquote></div>
</div></blockquote></div><br></div></div></div></blockquote></div>