> On May 27, 2016, at 11:54 AM, Austin Zheng via swift-evolution > <[email protected]> wrote: > > 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.) > > However, now that there is a conversation topic about reflection, I also > wanted to ask the following questions: > > 1. What sorts of features are important, and what would you use them for? > > For me, the list looks like the following: > > - Describe the structure of a type. (We have that right now, with > introspection using "Mirror".) > > - Find all the properties on a type. Get and set their values, and get > information about them (like their dynamic type). > - Find all the methods on a type. Be able to get a reference to and invoke a > method on an instance of a type. > - Find all the subscripts and initializers on a type? > > - Get a list of all concrete types opting in to extended reflection. > - Get a list of all concrete types visible to the caller that conform to some > protocol(s), possibly with additional requirements on associated types. > - Get a list of all protocols. > > - 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. > - Create a reference to a method or property using a string, and use it as > above. > > - 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. > > 2. What sorts of priorities should inform Swift's reflection capabilities? > > 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. > > 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. > > 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.
One priority you don’t mention here that I think is worthwhile to consider is static reflection. Any features that make sense both statically and dynamically should have the same API statically and dynamically wherever possible. > > Best, > Austin > > > >> On May 27, 2016, at 7:37 AM, plx via swift-evolution >> <[email protected] <mailto:[email protected]>> wrote: >> >> I think this proposal should “simmer" until we know what property behaviors >> will look like (or find out they are never happening, etc.). >> >> The interaction with “property behaviors” seems likely to be quite subtle, >> even for something simple like `lazy`. >> >> For sake of argument, let’s say that a `lazy` declaration like so: >> >> class SomeClass { >> lazy var foo: Foo = Foo(bar: self.prepareBar()) >> } >> >> …gets implicitly-expanded into e.g. something like the below: >> >> class SomeClass { >> >> var foo: Foo { >> guard let foo = _foo else { >> _foo = Foo(bar: self.prepareBar()) >> return _foo >> } >> return foo >> } >> >> private var _foo: Foo? = nil >> >> } >> >> …which immediately exposes a few lazy-specific questions: >> >> - should `foo` be exposed via reflection? (IMHO: yes) >> - should `_foo` be exposed via reflection? (IMHO: probably not, but not >> certain) >> - should `foo`’s lazy-ness be exposable? (IMHO: yes, but how exactly?) >> >> …as well as a few more-general questions: >> >> - should computed properties, in general, be exposed to reflection? (IMHO: >> probably not, but there are some exceptions…) >> - if user-specified property behaviors get special exposure, how should that >> work? >> - how should reflection work for enums/enums-with-payloads? >> >> 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. >> >> I don’t have any actual proposal on that front, but it seems like it should >> be factored into any reflection design. >> >>> On May 26, 2016, at 8:25 PM, Austin Zheng via swift-evolution >>> <[email protected] <mailto:[email protected]>> wrote: >>> >>> Hi swift-evolution, >>> >>> For those who are interested I'd like to present a pre-pre-proposal for >>> reflection upon a type's properties and solicit feedback. >>> >>> 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 defending this specific proposal per se, as I >>> am looking for a jumping-off point to explore designs in this space. >>> >>> Anyways, here is a gist outlining the public API to the feature: >>> >>> https://gist.github.com/austinzheng/699d47f50899b88645f56964c0b7109a >>> <https://gist.github.com/austinzheng/699d47f50899b88645f56964c0b7109a> >>> >>> A couple of notes regarding the proposal: >>> >>> The API names need improvement. Suggestions welcome. >>> >>> 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. >>> >>> 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. >>> >>> (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.) >>> >>> 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. >>> >>> 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. >>> >>> 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: >>> >>> ``` >>> myPerson.typedReadWriteProperty<Int>("age")?.set(30) >>> >>> try myPerson.allNamedProperties["age"]?.set(30) >>> ``` >>> >>> 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). >>> >>> I'd also have to figure out how it would operate with generic types or >>> existentials. >>> >>> Anyways, thanks for reading all the way to the end, and any feedback, >>> criticism, or alternative proposals would be greatly appreciated. >>> >>> Best, >>> Austin >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] <mailto:[email protected]> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] <mailto:[email protected]> >> https://lists.swift.org/mailman/listinfo/swift-evolution > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
