<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=""><div class="">How about a 5th way?</div><div class=""><br class=""></div><div class="">5. Let extensions introduce stored properties, but only in the same module as the type’s definition. Then, the compiler can just take any extensions into consideration when it’s determining the size of the type, just as if the properties had been declared in the type. Declaring stored properties on an extension outside of the type’s module results in a compiler error, exactly as today. This would, without any performance drawbacks, solve one of the big problems that people are hoping to solve via stored properties in extensions—the ability to organize members by protocol conformance. So, instead of this:</div><div class=""><br class=""></div><div class="">protocol P {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>var foo: String { get }</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>func bar()</div><div class="">}</div><div class=""><br class=""></div><div class="">protocol Q {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>var baz: Int { get }</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>func qux()</div><div class="">}</div><div class=""><br class=""></div><div class="">class C: P {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>var foo: String // <- what is this doing here?</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>var baz: Int // <- ditto</div><div class="">}</div><div class=""><br class=""></div><div class="">extension C: P {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>func bar() {}</div><div class="">}</div><div class=""><br class=""></div><div class="">extension C: Q {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>func qux() {}</div><div class="">}</div><div class=""><br class=""></div><div class="">we could simply:</div><div class=""><br class=""></div><div class=""><div class="">protocol P {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>var foo: String { get }</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func bar()</div><div class="">}</div></div><div class=""><br class=""></div><div class="">class C: P {}</div><div class=""><br class=""></div><div class="">extension C: P {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>var foo: String</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>func bar() {}</div><div class="">}</div><div class=""><br class=""></div><div class="">extension C: Q {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>var baz: Int</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>func qux() {}</div><div class="">}</div><div class=""><br class=""></div><div class="">So much cleaner, and since the compiler will simply turn the latter into the former at compile time, works without sacrificing anything in terms of performance.</div><div class=""><br class=""></div><div class="">Also, if we really decide that we need to have stored properties on *all* extensions, this idea still leaves the door open for using one of the methods discussed in this thread, in the case where the extension is in a different module from the original type.</div><div class=""><br class=""></div><div class="">Charles</div><br class=""><div><blockquote type="cite" class=""><div class="">On Oct 9, 2016, at 2:53 PM, Charlie Monroe via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">There is a 4th way.<div class=""><br class=""></div><div class="">Introduce an internal protocol Associatable, which would tell the compiler to add an additional (hidden) field to the object which would include the "dictionary" of key -> value associated values. (It would be off-limits to extensions, of course).</div><div class=""><br class=""></div><div class="">This way:</div><div class=""><br class=""></div><div class="">- it won't be a single dictionary containing all the associated values</div><div class="">- classes can opt-in to this</div><div class="">- the dictionary will be per-instance</div><div class=""><br class=""></div><div class="">This is a midway between the current implementation of ObjC associated objects and of what someone has suggested to have an extra space for each object for the AO...</div><div class=""><br class=""></div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Oct 9, 2016, at 9:47 PM, Jay Abbott via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class=""><div class=""><div class=""><div class="">I have been thinking further on this and in addition to my previous two thoughts about implementation, I have had another idea...<br class=""><br class=""></div>3. If there is a bit spare in the object header somewhere (that is currently always zero), this could be used to signify the presence of an additional struct that immediately follows after the existing object data. I *think* that this method would allow binary compatibility with older modules. Instances that have this bit set would allow stored properties in extensions. The struct at the end would have one member, a pointer to a table of additional objects/values, stored properties defined in extensions could be stored in here, using a hash derived from the module/protocol/extension/property name (or something better if it exists).<br class=""><br class=""></div>The struct could be very simple as described above or more complex, with additional features, for example a list of deinit hooks, dynamically added methods, etc. The struct itself may also be dynamic in size/layout if such complexity is warranted by size or extensibility concerns. Perhaps it should start with some flags and its size (size would be fixed and only increase with revisions so this would double as a 'version' number).<br class=""><br class=""></div>If viable - this would be a much better way to implement this feature than my previous two ideas. It doesn't require global lookups or additional levels of indirection beyond accessing the dynamic data/feature itself.<br class=""></div><div class=""><br class=""></div><div class=""><br class=""><div class=""><div class=""><div class=""><div class=""><div class="gmail_quote"><div dir="ltr" class="">On Mon, 3 Oct 2016 at 04:13 Jay Abbott <<a href="mailto:jay@abbott.me.uk" class="">jay@abbott.me.uk</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Are stored properties in extensions already being discussed elsewhere? Is this one of those deferred-but-not-indexed-anywhere subjects?<br class="gmail_msg"><br class="gmail_msg"></div>I wonder how stored properties could potentially be implemented, I can only think of two ways:<br class="gmail_msg"><br class="gmail_msg"></div>1. An extra pointer per instance (with resulting ABI compatability implications) to hold a collection of the stored items.<br class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">2. A global lookup for any instance where stored properties have been set.<br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I'm not a language implementation expert, or familiar with
the swift implementation, so there may be other/better ways - I'd like to know if there are?<br class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">If not, and option 2 was employed, a little foresight might enable the mechanism to be overloaded in the future for other dynamic features too. A bit flag (I'm hoping there's a spare bit in an existing flags field somewhere?) could indicate whether any feature had caused the object to be added to this lookup and deinit could check this bit and make sure the object is removed, thus any stored properties are nilled. The lookup value could be a struct with one member (extensionStoredProperties), and additional members can be added in future for new features.<br class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I get the impression from the associated objects discussion that perhaps there are much better, more optimal, more ingenious, more unknown-by-me ways of doing such things, so apologies if this whole idea is way-off the mark :D<br class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Jay<br class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">P.S. Note that stored properties in extensions could enable developers to implement their own dynamic features in Swift.. so such desires could be satisfied in the short term until they could be done properly in the language.<br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg"><div dir="ltr" class="gmail_msg">On Sat, 1 Oct 2016 at 00:49 Chris Lattner via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>> wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Sep 30, 2016, at 2:51 PM, Ted F.A. van Gaalen via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>> wrote:<br class="gmail_msg">
> Is it possible to have best of (these completely different) both worlds?<br class="gmail_msg">
<br class="gmail_msg">
Yes, of course it is. Your email spends a lot of words trying to form a false dichotomy. Swift can definitely have both awesome dynamic features while still having performance, predictability and safety.<br class="gmail_msg">
<br class="gmail_msg">
> Would it be possible in Swift to have facilities to generate objects<br class="gmail_msg">
> dynamically at runtime? and, if desirable, how can such be implemented?<br class="gmail_msg">
<br class="gmail_msg">
Here’s an extant implementation that you can use today:<br class="gmail_msg">
<a href="https://github.com/Zewo/Reflection" rel="noreferrer" class="gmail_msg" target="_blank">https://github.com/Zewo/Reflection</a><br class="gmail_msg">
<br class="gmail_msg">
I’m sure it isn’t ideal, but it proves that it can be done. When we have bandwidth to reevaluate this area from first principles, I’m sure we can make improvements on it.<br class="gmail_msg">
<br class="gmail_msg">
I will grant you that Smalltalk is a beautiful language in its simplicity, but for that simplicity it makes many tradeoffs that we’re not willing to make. We are willing to make the internal implementation of Swift complex if that means that we get a beautiful model for programmers - one that preserves the virtues of safety-by-default, predictability, performance, and joy-to-develop-in.<br class="gmail_msg">
<br class="gmail_msg">
The meme of “Swift can never (or will never) support dynamic features” is tired, and also wildly inaccurate.<br class="gmail_msg">
<br class="gmail_msg">
-Chris<br class="gmail_msg">
<br class="gmail_msg">
_______________________________________________<br class="gmail_msg">
swift-evolution mailing list<br class="gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
</blockquote></div></div></div></blockquote></div></div></div></div></div></div></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>