Skip to content

Instantly share code, notes, and snippets.

@andersio
Last active May 27, 2016 14:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andersio/9ff02257b5c89b35fd523dcd09e484e4 to your computer and use it in GitHub Desktop.
Save andersio/9ff02257b5c89b35fd523dcd09e484e4 to your computer and use it in GitHub Desktop.
prototype
public protocol PropertyDescribing {
/// The type or metatype the property belongs to.
associatedtype Container
/// The expected static type.
associatedtype Content
/// The name of the property.
var name: String { get }
/// The type of the property at runtime.
/// Assertion: `type` can be exactly `Content`, a subtype of `Content` or
/// a type that fits `Content` if `Content` is an existential (incl. `Any`).
var type: Any.Type { get }
}
public protocol MutablePropertyDescribing: PropertyDescribing {}
public struct PropertyDescriptor<Content, Container>: PropertyDescribing {
/// ...
/// Specializes the descriptor at runtime to `Value`.
/// `Value` can exactly `type`, a supertype of `type` or an existential (incl. `Any`)
/// that matches `type`.
///
/// `Value` needn't be inferred from the return type if the specializing function
/// proposal is accepted.
func specializing<Value>() -> PropertyDescriptor<Value, Container>
}
public struct MutablePropertyDescriptor<Content, Container>: MutablePropertyDescribing {
/// ...
/// Ditto.
func specializing<Value>() -> MutablePropertyDescriptor<Value, Container>
}
@magic protocol Reflectable {
public static func classProperties: [String: PropertyDescriptor<Any, Self>]
public static func mutableClassProperties: [String: MutablePropertyDescriptor<Any, Self>]
public static func properties: [String: PropertyDescriptor<Any, Self>]
public static func mutableProperties: [String: MutablePropertyDescriptor<Any, Self>]
/// Getter for instance properties and class properties.
public func getValue<Descriptor: PropertyDescribing where Descriptor.Container == Self>(using descriptor: Descriptor) -> Descriptor.Content
public mutating func setValue<Descriptor: MutablePropertyDescribing where Descriptor.Container == Self>(value: Descriptor.Content, using descriptor: Descriptor)
/// Setter forinstance properties and class properties.
public static func getValue<Descriptor: PropertyDescribing where Descriptor.Container == Self>(using descriptor: Descriptor) -> Descriptor.Content
public mutating static func setValue<Descriptor: MutablePropertyDescribing where Descriptor.Container == Self>(value: Descriptor.Content, using descriptor: Descriptor)
}
func callSite() {
/// Assuming `ReflectableClass` conforms to `CustomStringConvertible`.
let myObject = ReflectableClass()
/// "Non-typed" version.
let descriptor1 = ReflectableClass.properties["description"]!
let description1: Any = myObject.getValue(using: descriptor1)
/// Typed version.
let descriptor2 = ReflectableClass.properties["description"]!.specializing<String>()
let description2: String = myObject.getValue(using: descriptor2)
/// Let's try to request for a unrelated type.
let descriptor2 = ReflectableClass.properties["description"]!.specializing<Array<String>>()
/// Should result in a runtime error: The property `description` of type `String` in `ReflectableClass` is inconvertible to `Array<String>`.
/// Struct
let myValue = ReflectableStruct()
let descriptor3 = ReflectableStruct.mutableProperties["message"]!.specializing<String>()
myValue.setValue("Testing", using: descriptor3) /// Compiler Error: cannot mutate `myValue`.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment