<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="">For a concrete type, a partial initializer is a function that:<div class="">Can set `let` instance variables</div><div class="">May not refer to `self` in an rvalue</div><div class="">Must set the same subset of instance variables regardless of the code path taken</div><div class=""><br class=""></div><div class="">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 class=""><br class=""><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jun 25, 2017, at 3:57 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class="">So your proposed definition of a partial initializer is one that does not set any protocol requirement?<br class=""><div class="gmail_quote"><div dir="ltr" class="">On Sun, Jun 25, 2017 at 14:54 Robert Bennett &lt;<a href="mailto:rltbennett@icloud.com" class="">rltbennett@icloud.com</a>&gt; wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto" class=""><div class=""></div><div class="">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" class=""><div class=""><br class="">On Jun 25, 2017, at 3:33 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class="">On Sun, Jun 25, 2017 at 2:24 PM, Robert Bennett via swift-evolution <span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</span> wrote:<br class=""><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 class="">
<br class="">
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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Example code:<br class="">
<br class="">
protocol P {<br class="">
&nbsp; &nbsp; var x: Int { let } // or { get set(init) }, or whatever<br class="">
<br class="">
&nbsp; &nbsp; partialinit initializeRest()<br class="">
&nbsp; &nbsp; init()<br class="">
}<br class="">
<br class="">
extension P {<br class="">
&nbsp; &nbsp; init() {<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; initializeRest()<br class=""></blockquote><div class=""><br class=""></div><div class="">How can the compiler ensure that `initializeRest()` does not already set `x`?</div><div class="">&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 class="">
<span class="">&nbsp; &nbsp; }<br class="">
}<br class="">
<br class="">
struct S: P {<br class="">
&nbsp; &nbsp; let x: Int<br class="">
</span>&nbsp; &nbsp; var y: String<br class="">
<br class="">
&nbsp; &nbsp; // It would be a compiler error to set x here without also redefining init()<br class="">
&nbsp; &nbsp; partialinit initializeRest() {<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; self.y = “P has no knowledge of me”<br class="">
&nbsp; &nbsp; }<br class="">
<br class="">
&nbsp; &nbsp; // Can use default init provided by P<br class="">
<div class="m_8744431084820982882HOEnZb"><div class="m_8744431084820982882h5">}<br class="">
<br class="">
&gt; On Jun 23, 2017, at 8:12 PM, Karl Wagner &lt;<a href="mailto:razielim@gmail.com" target="_blank" class="">razielim@gmail.com</a>&gt; wrote:<br class="">
&gt;<br class="">
&gt; What you want is some way to guarantee value semantics when writing generic code.<br class="">
&gt;<br class="">
&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 class="">
&gt;<br class="">
&gt; - Karl<br class="">
&gt;<br class="">
&gt;&gt; On 23. Jun 2017, at 23:43, Robert Bennett via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class="">
&gt;&gt;<br class="">
&gt;&gt; Hello Swift Evolution,<br class="">
&gt;&gt;<br class="">
&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 class="">
&gt;&gt;<br class="">
&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 class="">
&gt;&gt;<br class="">
&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 class="">
&gt;&gt;<br class="">
&gt;&gt; protocol P {<br class="">
&gt;&gt;&nbsp; &nbsp;var x: Int { let }<br class="">
&gt;&gt;&nbsp; &nbsp;init(_ x: Int)<br class="">
&gt;&gt;&nbsp; &nbsp;func modifyX()<br class="">
&gt;&gt; }<br class="">
&gt;&gt; extension P {<br class="">
&gt;&gt;&nbsp; &nbsp;init(_ x: Int) {<br class="">
&gt;&gt;&nbsp; &nbsp; &nbsp; &nbsp;self.x = x // This is ok; would not be ok if x were marked { get }<br class="">
&gt;&gt;&nbsp; &nbsp;}<br class="">
&gt;&gt;<br class="">
&gt;&gt;&nbsp; &nbsp;func modifyX() {<br class="">
&gt;&gt;&nbsp; &nbsp; &nbsp; &nbsp;self.x += 1 // Not allowed<br class="">
&gt;&gt;&nbsp; &nbsp;}<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; struct S: P {<br class="">
&gt;&gt;&nbsp; &nbsp;let x: Int // This is ok; would not be ok if x were marked { get set }<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; Option 2: `set(init)`. Can (and often will) coexist with `get`.<br class="">
&gt;&gt;<br class="">
&gt;&gt; protocol P {<br class="">
&gt;&gt;&nbsp; &nbsp;var x: Int { get set(init) }<br class="">
&gt;&gt;&nbsp; &nbsp;init(_ x: Int)<br class="">
&gt;&gt;&nbsp; &nbsp;func modifyX()<br class="">
&gt;&gt; }<br class="">
&gt;&gt; extension P {<br class="">
&gt;&gt;&nbsp; &nbsp;init(_ x: Int) {<br class="">
&gt;&gt;&nbsp; &nbsp; &nbsp; &nbsp;self.x = x // This is ok; would not be ok if x were marked { get }<br class="">
&gt;&gt;&nbsp; &nbsp;}<br class="">
&gt;&gt;<br class="">
&gt;&gt;&nbsp; &nbsp;func modifyX() {<br class="">
&gt;&gt;&nbsp; &nbsp; &nbsp; &nbsp;self.x += 1 // Not allowed<br class="">
&gt;&gt;&nbsp; &nbsp;}<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; struct S: P {<br class="">
&gt;&gt;&nbsp; &nbsp;let x: Int // This is ok; would not be ok if x were marked { get set }<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt;<br class="">
&gt;&gt; I’d like to hear all of your thoughts on this.<br class="">
&gt;&gt;<br class="">
&gt;&gt; Best,<br class="">
&gt;&gt; Robert<br class="">
&gt;&gt; _______________________________________________<br class="">
&gt;&gt; swift-evolution mailing list<br class="">
&gt;&gt; <a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">
&gt;&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
&gt;<br class="">
_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</div></div></blockquote></div><br class=""></div></div>
</div></blockquote></div></blockquote></div>
</div></blockquote></div><br class=""></div></div></body></html>