<div dir="ltr"><div class="markdown-here-wrapper" style=""><p style="margin:0px 0px 1.2em!important">I think if we start to discuss composition as part of the language, it could solve this issue.</p>
<p style="margin:0px 0px 1.2em!important">In my composition pitch I didn’t go into great detail (and nothing about properties in components at this early stage - I figured I should start simple and we can think it through further as a group), but if we had a syntax for composing types out of <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">component</code>s (implementations of protocols), you could include a guarantee that a <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">component</code> were initialised in <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">init</code>. This would also solve the partial initialisation issue - as a <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">component</code> is a complete implementation of a particular protocol, which can be fully initialised itself, before the composed type is fully initialised.</p>
<div title="MDH:PGRpdj48ZGl2PkkgdGhpbmsgaWYgd2Ugc3RhcnQgdG8gZGlzY3VzcyBjb21wb3NpdGlvbiBhcyBw
YXJ0IG9mIHRoZSBsYW5ndWFnZSwgaXQgY291bGQgc29sdmUgdGhpcyBpc3N1ZS48YnI+PGJyPjwv
ZGl2PkluIG15IGNvbXBvc2l0aW9uIHBpdGNoIEkgZGlkbid0IGdvIGludG8gZ3JlYXQgZGV0YWls
IChhbmQgbm90aGluZyBhYm91dCBwcm9wZXJ0aWVzIGluIGNvbXBvbmVudHMgYXQgdGhpcyBlYXJs
eSBzdGFnZSAtIEkgZmlndXJlZCBJIHNob3VsZCBzdGFydCBzaW1wbGUgYW5kIHdlIGNhbiB0aGlu
ayBpdCB0aHJvdWdoIGZ1cnRoZXIgYXMgYSBncm91cCksIGJ1dCBpZiB3ZSBoYWQgYSBzeW50YXgg
Zm9yIGNvbXBvc2luZyB0eXBlcyBvdXQgb2YgYGNvbXBvbmVudGBzIChpbXBsZW1lbnRhdGlvbnMg
b2YgcHJvdG9jb2xzKSwgeW91IGNvdWxkIGluY2x1ZGUgYSBndWFyYW50ZWUgdGhhdCBhIGBjb21w
b25lbnRgIHdlcmUgaW5pdGlhbGlzZWQgaW4gYGluaXRgLiBUaGlzIHdvdWxkIGFsc28gc29sdmUg
dGhlIHBhcnRpYWwgaW5pdGlhbGlzYXRpb24gaXNzdWUgLSBhcyBhIGBjb21wb25lbnRgIGlzIGEg
Y29tcGxldGUgaW1wbGVtZW50YXRpb24gb2YgYSBwYXJ0aWN1bGFyIHByb3RvY29sLCB3aGljaCBj
YW4gYmUgZnVsbHkgaW5pdGlhbGlzZWQgaXRzZWxmLCBiZWZvcmUgdGhlIGNvbXBvc2VkIHR5cGUg
aXMgZnVsbHkgaW5pdGlhbGlzZWQuPGJyPjwvZGl2Pg==" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0">​</div></div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, 27 Jun 2017 at 00:00 Karl Wagner via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</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"><br><div><blockquote type="cite"><div>On 26. Jun 2017, at 13:44, Karl Wagner &lt;<a href="mailto:razielim@gmail.com" target="_blank">razielim@gmail.com</a>&gt; wrote:</div><br class="m_1731055805810111260Apple-interchange-newline"><div><div><br><blockquote type="cite">On 25. Jun 2017, at 22:13, Robert Bennett &lt;<a href="mailto:rltbennett@icloud.com" target="_blank">rltbennett@icloud.com</a>&gt; wrote:<br><br>For a concrete type, a partial initializer is a function that:<br>Can set `let` instance variables<br>May not refer to `self` in an rvalue<br>Must set the same subset of instance variables regardless of the code path taken<br><br>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.<br><br></blockquote><br>I’ll say again: I think you’re approaching this from the wrong angle. You want stronger guarantees about mutability of properties, but the answer is not to make protocols be more restrictive about how conformers are written.<br><br>What you are really asking for is the guarantee that some type which conforms to SomeProtocol has value-semantics. Once you have that guarantee, you know that you have a unique instance whose properties will only mutate if they are stored in a “var” property and you yourself mutate it.<br><br>For example, an Array’s “count” property is technically a computed property, but in a “let”-declared Array you can treat it as a “let” constant because Arrays have value semantics. Your guarantees about properties only being set in the initialiser would automatically be fulfilled without the need of any additional alternate initialisation patterns.<br><br>- Karl</div></div></blockquote></div><br></div><div style="word-wrap:break-word"><div>Just to expand on this a little bit, as I see it there are two parts to your problem. First, you were asking for some kind of partial-initialisation. Second, you (or somebody) mentioned that there might be optimisation benefits.</div><div><br></div><div>Here’s a kind of partial initialisation you can use right now:</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><font face="Menlo">public protocol SomeProtocol {<br>    var neverReallyMutatesAfterInit: String { get }<br>}<br><br>public extension SomeProtocol {<br>    static func withProtocolDefaults() -&gt; SomeProtocol? {<br>        return (Self.self as? PartiallyInitializableSomeProtocol.Type).map { $0.withProtocolDefaults() }<br>    }<br>}<br><br>internal protocol PartiallyInitializableSomeProtocol: SomeProtocol {<br><br>    /// Creates an object with type-specific defaults.<br>    init()<br><br>    /// Allows customisation by the protocol after init.<br>    var neverReallyMutatesAfterInit: String { get set }<br>}<br><br>internal extension PartiallyInitializableSomeProtocol {<br>     static func withProtocolDefaults() -&gt; SomeProtocol {<br>        var newValue = Self()<br>        newValue.neverReallyMutatesAfterInit = &quot;ProtocolDefault&quot;<br>        return newValue<br>    }<br>}<br><br>public struct SomeConformer: PartiallyInitializableSomeProtocol {<br>    public internal(set) var neverReallyMutatesAfterInit = &quot;TypeDefault&quot;<br>    internal init() {}<br>}<br><br>(SomeConformer.self as SomeProtocol.Type).withProtocolDefaults()?.neverReallyMutatesAfterInit // &quot;ProtocolDefault&quot;</font></div></div><div><font face="Menlo"><br></font></div><div><font face="Menlo"><br></font></div></blockquote><div>With this example, the only way users of your library can obtain an instance is via the protocol function, which knows that it can construct a default instance and specialise the values.</div><div><br></div><div>As far as optimisation goes - I have to correct myself, because even in a protocol existential whose underlying type is known to have value semantics, computed properties themselves might not. For all the compiler knows, they could be reading/writing from global state. So the compiler can’t really eliminate repeat accesses unless it knows the underlying implementation (or we give it more information about how the content mutates). People have asked about marking stored/computed properties in protocols before, and I’ve always been against it. Protocols should contain abstract, semantic information with as little implementation-constraining stuff as possible whilst retaining the contract. That’s what makes them so powerful.</div></div><div style="word-wrap:break-word"><div><br></div><div>- Karl</div></div>_______________________________________________<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>
</blockquote></div>