<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=""><br class=""><div><blockquote type="cite" class=""><div class="">On May 27, 2016, at 11:54 AM, Austin Zheng via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; 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=""><div class="">I think there is a consensus forming that we probably don't yet know enough about Swift's future capabilities to nail down specific designs yet. (Not that I want to stop people from talking about them if they wish.)</div><div class=""><br class=""></div><div class="">However, now that there is a conversation topic about reflection, I also wanted to ask the following questions:</div><div class=""><br class=""></div><div class="">1. What sorts of features are important, and what would you use them for?</div><div class=""><br class=""></div><div class="">For me, the list looks like the following:</div><div class=""><br class=""></div><div class="">- Describe the structure of a type. (We have that right now, with introspection using "Mirror".)</div><div class=""><br class=""></div><div class="">- Find all the properties on a type. Get and set their values, and get information about them (like their dynamic type).</div><div class="">- Find all the methods on a type. Be able to get a reference to and invoke a method on an instance of a type.</div><div class="">- Find all the subscripts and initializers on a type?</div><div class=""><br class=""></div><div class="">- Get a list of all concrete types opting in to extended reflection.</div><div class="">- Get a list of all concrete types visible to the caller that conform to some protocol(s), possibly with additional requirements on associated types.</div><div class="">- Get a list of all protocols.</div><div class=""><br class=""></div><div class="">- Create a reference to a type using a string, and perform certain actions using that type. (It would be interesting if you could say "try parsing this type into a concrete type that conforms to X, Y, and Z protocols", and if successful you get a metatype to use or something you can pass to a generic function.</div><div class="">- Create a reference to a method or property using a string, and use it as above.</div><div class=""><br class=""></div><div class="">- Reify methods and properties marked with the 'dynamic' keyword in such a way that where they are dispatched to can be controlled at runtime. For example, maybe a dynamic method of a class might use some default implementation, or if some condition is met forward invocations of it to a dynamic method on another class instead.</div><div class=""><br class=""></div><div class="">2. What sorts of priorities should inform Swift's reflection capabilities?</div><div class=""><br class=""></div><div class="">For me, the option to perform both "statically typed" and runtime type checked operations, when feasible, is a big one. I think something like variadic generics could allow for typesafe reflection on methods and functions at runtime - rather than having to call a performSelector: like method, it would be possible to get a full-fledged value of function type and use it just like any other method. This is something few languages have AFAIK.</div><div class=""><br class=""></div><div class="">The reflection machinery should cooperate with the rest of the language. If there must be a way to, for example, access private members of an instance through reflection, it should not be unconditional and should be carefully considered such that there are certain invariants that are still honored. Like Laurent said earlier, bad things can happen if you use reflection to subvert access control.</div><div class=""><br class=""></div><div class="">I think reflection should be opt-in in most cases. Reflection opting-in should be composable, inheritable, and retroactive, which covers the most common cases in which reflection would be useful: working with Cocoa/Cocoa Touch, for example.</div></div></div></blockquote><div><br class=""></div><div>One priority you don’t mention here that I think is worthwhile to consider is static reflection. &nbsp;Any features that make sense both statically and dynamically should have the same API statically and dynamically wherever possible. &nbsp;</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">Best,</div><div class="">Austin</div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On May 27, 2016, at 7:37 AM, plx via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; 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=""><div class="">I think this proposal should “simmer" until we know what property behaviors will look like (or find out they are never happening, etc.).&nbsp;</div><div class=""><br class=""></div><div class="">The interaction with “property behaviors” seems likely to be quite subtle, even for something simple like `lazy`.</div><div class=""><br class=""></div><div class="">For sake of argument, let’s say that a `lazy` declaration like so:</div><div class=""><br class=""></div><div class=""><div class="">&nbsp; class SomeClass {&nbsp;</div><div class="">&nbsp; &nbsp; lazy var foo: Foo = Foo(bar: self.prepareBar())</div><div class="">&nbsp; }</div></div><div class=""><br class=""></div><div class="">…gets implicitly-expanded into e.g. something like the below:</div><div class=""><br class=""></div><div class=""><div class=""><div class="">&nbsp; class SomeClass {</div><div class="">&nbsp;</div><div class="">&nbsp; &nbsp; var foo: Foo {</div><div class="">&nbsp; &nbsp; &nbsp; guard let foo = _foo else {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; _foo = Foo(bar: self.prepareBar())</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; return _foo</div><div class="">&nbsp; &nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; &nbsp; return foo</div><div class="">&nbsp; &nbsp; }</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; private var _foo: Foo? = nil</div><div class=""><br class=""></div><div class="">&nbsp; }</div></div></div><div class=""><br class=""></div><div class="">…which immediately exposes a few lazy-specific questions:</div><div class=""><br class=""></div><div class="">- should `foo` be exposed via reflection? (IMHO: yes)</div><div class="">- should `_foo` be exposed via reflection? (IMHO: probably not, but not certain)</div><div class="">- should `foo`’s lazy-ness be exposable? (IMHO: yes, but how exactly?)</div><div class=""><br class=""></div><div class="">…as well as a few more-general questions:</div><div class=""><br class=""></div><div class="">- should computed properties, in general, be exposed to reflection? (IMHO: probably not, but there are some exceptions…)</div><div class="">- if user-specified property behaviors get special exposure, how should that work?</div><div class="">- how should reflection work for enums/enums-with-payloads?&nbsp;</div><div class=""><br class=""></div><div class="">Finally, I worry a lot less about the details of getter/setter pairs than I worry about being able to use reflection for construction/initialization.</div><div class=""><br class=""></div><div class="">I don’t have any actual proposal on that front, but it seems like it should be factored into any reflection design.</div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On May 26, 2016, at 8:25 PM, Austin Zheng via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Hi swift-evolution,<div class=""><br class=""></div><div class="">For those who are interested I'd like to present a pre-pre-proposal for reflection upon a type's properties and solicit feedback.&nbsp;</div><div class=""><br class=""></div><div class="">First of all, some caveats: this is only a very small piece of what reflection in Swift might look like one day, and it's certainly not the only possible design for such a feature. Reflection comes in many different forms, and "no reflection" is also an option. Deciding what sort of reflection capabilities Swift should support is a prerequisite to stabilizing the runtime API, which I imagine has resilience consequences. I'm not really interested in <i class="">defending</i>&nbsp;this specific proposal per se, as I am looking for a jumping-off point to explore designs in this space.</div><div class=""><br class=""></div><div class="">Anyways, here is a gist outlining the public API to the feature:&nbsp;</div><div class=""><br class=""></div><div class=""><a href="https://gist.github.com/austinzheng/699d47f50899b88645f56964c0b7109a" class="">https://gist.github.com/austinzheng/699d47f50899b88645f56964c0b7109a</a><br class=""></div><div class=""><br class=""></div><div class="">A couple of notes regarding the proposal:</div><div class=""><br class=""></div><div class="">The API names need improvement. Suggestions welcome.</div><div class=""><br class=""></div><div class="">It's opt-in: types have to conform to a special protocol for the compiler to generate whatever hooks, metadata, and support code is necessary. Once a type conforms, the interface to the reflection features naturally present themselves as protocol methods. It would be great to allow an extension to retroactively enable reflection on a type vended by another module, although I have no idea how feasible that is.</div><div class=""><br class=""></div><div class="">It uses "views": there are four types of views, two of each in the following categories: typed vs untyped, get-only versus get-set. A view is a struct representing a property on an instance of a type (or maybe a metatype, for type properties). It allows you to get information about that property (like its name) and try getting and setting its values.</div><div class=""><br class=""></div><div class="">(You can get a get-only view to a property, and then try and upgrade it later to a get-set view, if the underlying property is get-set. If you don't care about setting, though, you can just work exclusively with get-only views.)</div><div class=""><br class=""></div><div class="">It supports both typed and untyped access. You can ask for a property view specifically for (e.g.) a `String` property, and if you get one you can be assured that your getting and setting operations will be type safe. You can also ask for an "untyped" property view that exposes the value as an Any, and allows you to try (and possibly fail, with a thrown error) to set the value.</div><div class=""><br class=""></div><div class="">The requirements part of it is composable. For example, you can imagine a future "FullyReflectable" protocol that simply inherits from "PropertyReflectable", "MethodReflectable", and other reflectable protocols. Or maybe a library requires reflection access to types that it needs to work with, and it can create its own protocols that inherit from "PropertyReflectable" and naturally enforce reflection support on the necessary types.</div><div class=""><br class=""></div><div class="">It looks a bit cumbersome, but there's room for refinement. Users won't necessarily see all the types, though, and the interface is pretty straightforward:</div><div class=""><br class=""></div><div class="">```</div><div class="">myPerson.typedReadWriteProperty&lt;Int&gt;("age")?.set(30)</div><div class=""><br class=""></div><div class="">try myPerson.allNamedProperties["age"]?.set(30)</div><div class="">```</div><div class=""><br class=""></div><div class="">I'm not yet sure how it should interact with access control (my inclination is that it would only expose the properties you'd be able to directly access), or property behaviors (I think get-set behavior is fundamental to properties, although "behavior metadata" on the views might be useful).</div><div class=""><br class=""></div><div class="">I'd also have to figure out how it would operate with generic types or existentials.</div><div class=""><br class=""></div><div class="">Anyways, thanks for reading all the way to the end, and any feedback, criticism, or alternative proposals would be greatly appreciated.</div><div class=""><br class=""></div><div class="">Best,</div><div class="">Austin</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>_______________________________________________<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>_______________________________________________<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>