<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 <<a href="mailto:xiaodi.wu@gmail.com">xiaodi.wu@gmail.com</a>> 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"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></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 class=""> }<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="HOEnZb"><div class="h5">}<br>
<br>
> On Jun 23, 2017, at 8:12 PM, Karl Wagner <<a href="mailto:razielim@gmail.com">razielim@gmail.com</a>> wrote:<br>
><br>
> What you want is some way to guarantee value semantics when writing generic code.<br>
><br>
> 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>
><br>
> - Karl<br>
><br>
>> On 23. Jun 2017, at 23:43, Robert Bennett via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br>
>><br>
>> Hello Swift Evolution,<br>
>><br>
>> 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>
>><br>
>> 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>
>><br>
>> 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>
>><br>
>> protocol P {<br>
>> var x: Int { let }<br>
>> init(_ x: Int)<br>
>> func modifyX()<br>
>> }<br>
>> extension P {<br>
>> init(_ x: Int) {<br>
>> self.x = x // This is ok; would not be ok if x were marked { get }<br>
>> }<br>
>><br>
>> func modifyX() {<br>
>> self.x += 1 // Not allowed<br>
>> }<br>
>> }<br>
>><br>
>> struct S: P {<br>
>> let x: Int // This is ok; would not be ok if x were marked { get set }<br>
>> }<br>
>><br>
>> Option 2: `set(init)`. Can (and often will) coexist with `get`.<br>
>><br>
>> protocol P {<br>
>> var x: Int { get set(init) }<br>
>> init(_ x: Int)<br>
>> func modifyX()<br>
>> }<br>
>> extension P {<br>
>> init(_ x: Int) {<br>
>> self.x = x // This is ok; would not be ok if x were marked { get }<br>
>> }<br>
>><br>
>> func modifyX() {<br>
>> self.x += 1 // Not allowed<br>
>> }<br>
>> }<br>
>><br>
>> struct S: P {<br>
>> let x: Int // This is ok; would not be ok if x were marked { get set }<br>
>> }<br>
>><br>
>><br>
>> I’d like to hear all of your thoughts on this.<br>
>><br>
>> Best,<br>
>> Robert<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>
><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>