[swift-evolution] stored properties in extensions (was: associated objects)

Jay Abbott jay at abbott.me.uk
Mon Oct 10 06:13:08 CDT 2016


I understand Charlie. A few points though:
a) I'm talking about pure Swift, this is absolutely nothing to do with
Objective-C;
b) If you read back on the AO thread you'll see that initially I was
thinking "I want AO because it will give me stored properties in
extensions" when really I should have been thinking "I want stored
properties in extensions". So this discussion is no longer about AO at all,
hence the new subject.
c) Protocol conformance in an extension cannot tell the compiler to add
members to classes defined in other precompiled modules, as it is not
compiling them. When you do have the code and you are compiling it
yourself, you actually don't *need* stored properties in extensions because
you can work around it (although it would be nice), so the case where you
actually need it is where you want to extend someone else's precompiled
class.

On Mon, 10 Oct 2016 at 06:04 Charlie Monroe <charlie at charliemonroe.net>
wrote:

> No, I've also suggested how it would be implemented. It would, as I've
> described, require support from the compiler and runtime - the protocol
> conformance would tell the compiler to include an extra space in the
> instance layout for [AnyHashable : Any], which would get to be used by the
> runtime to store AO.
>
> Note that the implementation noted below does not use any locks at all -
> unlike ObjC AO, it's not thread-safe.
>
> With AO, the main bottleneck always was that everything was stored in one
> place - this way, each object would have its own AOs stored within itself.
> This way, instead of a single spin (!) lock (
> https://opensource.apple.com/source/objc4/objc4-680/runtime/objc-references.mm),
> you can use a lock pool - e.g. you have a dozen locks, depending on the
> hash of the object itself, you decide which lock to use - this lowers the
> contention a lot.
>
> Try to run a few threads, read, write AO using the ObjC runtime - you'll
> see how painfully slow it is - this is not something that should be in
> Swift.
>
>
> On Oct 9, 2016, at 10:15 PM, Jay Abbott <jay at abbott.me.uk> wrote:
>
> Charlie,
>
> What you suggest defines how you would use it from your code, not how it
> would be implemented in the language. If you look at my AO implementation
> it does what you say:
>
> https://github.com/j-h-a/AssociatedObjects/blob/develop/AssociatedObjects/AssociatedObjects.swift
> i.e. has a protocol called 'Associable' and you opt classes into it to get
> the behaviour. This works and is usable, but the implementation leaves a
> lot to be desired (it's not optimal and while the interface is clean the
> implementation is not). Anyway - I was trying to steer the conversation
> AWAY from AOs towards stored properties in extensions, since Robert Widmann
> helped me to understand that AO was just a *means*, whereas stored
> properties in extensions is the *end*.
>
> In fact we don't need a solution to the problem of "how to define/use
> stored properties in extensions" because the existing syntax for extensions
> is perfectly fine. Currently you get an error if you try to define a stored
> property in an extension, so no new syntax is needed, we just remove that
> error and make it work.
>
> Of course a runtime-check may be needed if there is doubt about whether a
> dynamically linked module supported this feature - so this might invalidate
> what I just said above, or it might still be possible if the runtime does
> the check automatically when an extension is linked and puts a different
> implementation in place for older modules.
>
> I'm just airing some thoughts at the moment to see what people think and
> try to get some technical feedback on viability. So it's not all fully
> thought through :D
>
>
> On Sun, 9 Oct 2016 at 20:54 Charlie Monroe <charlie at charliemonroe.net>
> wrote:
>
> There is a 4th way.
>
> 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).
>
> This way:
>
> - it won't be a single dictionary containing all the associated values
> - classes can opt-in to this
> - the dictionary will be per-instance
>
> 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...
>
>
> On Oct 9, 2016, at 9:47 PM, Jay Abbott via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I have been thinking further on this and in addition to my previous two
> thoughts about implementation, I have had another idea...
>
> 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).
>
> 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).
>
> 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.
>
>
> On Mon, 3 Oct 2016 at 04:13 Jay Abbott <jay at abbott.me.uk> wrote:
>
> Are stored properties in extensions already being discussed elsewhere? Is
> this one of those deferred-but-not-indexed-anywhere subjects?
>
> I wonder how stored properties could potentially be implemented, I can
> only think of two ways:
>
> 1. An extra pointer per instance (with resulting ABI compatability
> implications) to hold a collection of the stored items.
>
> 2. A global lookup for any instance where stored properties have been set.
>
> 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?
>
> 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.
>
> 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
>
> Jay
>
> 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.
>
> On Sat, 1 Oct 2016 at 00:49 Chris Lattner via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> On Sep 30, 2016, at 2:51 PM, Ted F.A. van Gaalen via swift-evolution <
> swift-evolution at swift.org> wrote:
> > Is it possible to have best of (these completely different) both worlds?
>
> 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.
>
> > Would it be possible in Swift to have facilities to generate objects
> > dynamically at runtime? and, if desirable, how can such be implemented?
>
> Here’s an extant implementation that you can use today:
> https://github.com/Zewo/Reflection
>
> 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.
>
> 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.
>
> The meme of “Swift can never (or will never) support dynamic features” is
> tired, and also wildly inaccurate.
>
> -Chris
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161010/2cc17fc4/attachment.html>


More information about the swift-evolution mailing list