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:
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