<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body 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><br>On Jun 25, 2017, at 3:33 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com">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>
&nbsp; &nbsp; var x: Int { let } // or { get set(init) }, or whatever<br>
<br>
&nbsp; &nbsp; partialinit initializeRest()<br>
&nbsp; &nbsp; init()<br>
}<br>
<br>
extension P {<br>
&nbsp; &nbsp; init() {<br>
&nbsp; &nbsp; &nbsp; &nbsp; initializeRest()<br></blockquote><div><br></div><div>How can the compiler ensure that `initializeRest()` does not already set `x`?</div><div>&nbsp;</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
&nbsp; &nbsp; &nbsp; &nbsp; self.x = 1<br>
<span class="">&nbsp; &nbsp; }<br>
}<br>
<br>
struct S: P {<br>
&nbsp; &nbsp; let x: Int<br>
</span>&nbsp; &nbsp; var y: String<br>
<br>
&nbsp; &nbsp; // It would be a compiler error to set x here without also redefining init()<br>
&nbsp; &nbsp; partialinit initializeRest() {<br>
&nbsp; &nbsp; &nbsp; &nbsp; self.y = “P has no knowledge of me”<br>
&nbsp; &nbsp; }<br>
<br>
&nbsp; &nbsp; // Can use default init provided by P<br>
<div class="HOEnZb"><div class="h5">}<br>
<br>
&gt; On Jun 23, 2017, at 8:12 PM, Karl Wagner &lt;<a href="mailto:razielim@gmail.com">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">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;&nbsp; &nbsp;var x: Int { let }<br>
&gt;&gt;&nbsp; &nbsp;init(_ x: Int)<br>
&gt;&gt;&nbsp; &nbsp;func modifyX()<br>
&gt;&gt; }<br>
&gt;&gt; extension P {<br>
&gt;&gt;&nbsp; &nbsp;init(_ x: Int) {<br>
&gt;&gt;&nbsp; &nbsp; &nbsp; &nbsp;self.x = x // This is ok; would not be ok if x were marked { get }<br>
&gt;&gt;&nbsp; &nbsp;}<br>
&gt;&gt;<br>
&gt;&gt;&nbsp; &nbsp;func modifyX() {<br>
&gt;&gt;&nbsp; &nbsp; &nbsp; &nbsp;self.x += 1 // Not allowed<br>
&gt;&gt;&nbsp; &nbsp;}<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; struct S: P {<br>
&gt;&gt;&nbsp; &nbsp;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;&nbsp; &nbsp;var x: Int { get set(init) }<br>
&gt;&gt;&nbsp; &nbsp;init(_ x: Int)<br>
&gt;&gt;&nbsp; &nbsp;func modifyX()<br>
&gt;&gt; }<br>
&gt;&gt; extension P {<br>
&gt;&gt;&nbsp; &nbsp;init(_ x: Int) {<br>
&gt;&gt;&nbsp; &nbsp; &nbsp; &nbsp;self.x = x // This is ok; would not be ok if x were marked { get }<br>
&gt;&gt;&nbsp; &nbsp;}<br>
&gt;&gt;<br>
&gt;&gt;&nbsp; &nbsp;func modifyX() {<br>
&gt;&gt;&nbsp; &nbsp; &nbsp; &nbsp;self.x += 1 // Not allowed<br>
&gt;&gt;&nbsp; &nbsp;}<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; struct S: P {<br>
&gt;&gt;&nbsp; &nbsp;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; ______________________________<wbr>_________________<br>
&gt;&gt; swift-evolution mailing list<br>
&gt;&gt; <a href="mailto:swift-evolution@swift.org">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/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
&gt;<br>
______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
</div></div></blockquote></div><br></div></div>
</div></blockquote></body></html>