>> I'm not sure how much metadata is necessary beyond name (in the key) and >> type (discussed soon). > > In the future we may have user-defined attributes. It could be very useful > to expose that.
This is true. Actually, I'm wondering if property behaviors should be able to essentially declare alternate PropertyViews and add their properties to them. For instance: var behavior persistent<Value: PersistentValue>: Value where Self: ManagedObject { belongsto persistentProperties, static persistentInstanceProperties name: String var value: Value init() { value = entity.propertiesByName[name].defaultValue } get { return value } set { value = newValue } } protocol Managed { static var persistentProperties: InstancePropertyView<Self> { get } var persistentProperties: PropertyView<Self> { get set } ... } class Person: Managed { @persistent var name: String @persistent var birthDate: Date } print(Person.persistentProperties.keys) // => "name", "birthDate" I think it's probably more likely that you want to access the subset of properties with a particular attribute than that you want to look through all the properties and check whether each one has or doesn't have that attribute. (Incidentally, this is beginning to look a little like one of the post-@memberwise proposals to have some sort of entity representing a group of properties—only more flexible and with a broader set of use cases. Still, there might be hope for a solution with a `@memberwise` behavior and a macro to look at the resulting property view and generate an initializer from it.) >> Yes. I would hope that you could downcast a concrete lens: >> >> let lens: () -> inout Int = &array.count >> // Assuming this is a "get lens” syntax > > I think the syntax was actually a little bit different as the lens isn’t > bound to the instance and a readonly lens wouldn’t return inout: > > let lens: (Array<MyType>) -> Int = &array.count I envision there being both bound lenses (sorry, I forgot that `Array.count` isn't mutating): struct Person { var name: String } var joe = Person(name: "Joe") let lens: () -> inout String = &joe.name And unbound ones: let unboundLens: (inout Person) -> inout String = Person.name `properties` on an instance would give you bound lenses; `properties` on a type would give you unbound ones. (Or maybe the latter would be something like `instanceProperties`, since type instances have properties too.) On the other hand, the idea of bound lenses might not be coherent; the `inout` parameter of an unbound lens helps make sure that mutation affects value-typed instances, so bound lenses might not work. Perhaps `properties` on an instance should be more akin to a `[String: Any]` dictionary, so that `joe.properties["name"] = "Bob"` naturally calls `joe`'s `properties` setter. The problem I see there is that the `openas` might open things too far: If the property is declared to be of protocol type, `openas` would end up giving you the concrete type of its current value instead. >> And that you could later open the abstracted lens to get its concrete type: >> >> if let concreteLens = abstractLens openas Lens { >> print(Lens.ReturnValue) >> … >> } > > What about casting like this: > > let typedLens = abstractLens as? (Array<MyType>) -> Int If you're specifically expecting an `Int`, sure. But if you have no idea what the type is and want to find out, I think you'd need to (somehow) open the Any lens and see the concrete return type inside. -- Brent Royal-Gordon Architechies _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution