Last active
May 27, 2016 14:56
-
-
Save andersio/9ff02257b5c89b35fd523dcd09e484e4 to your computer and use it in GitHub Desktop.
prototype
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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