> On May 27, 2016, at 5:37 PM, Anders Ha <[email protected]> wrote:
>
>>
>> On 28 May 2016, at 6:00 AM, Brent Royal-Gordon via swift-evolution
>> <[email protected]> wrote:
>>
>>>> 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.
>
> In this case, I wonder if it would be less confusing if bound lenses are
> available only on reference types, or existential with a class bound.
It could be very useful be able to pass a lens bound to a value type as a
nonescaping argument. The implementation would have to guarantee the bound
lens can’t escape the effective scope of the value. I don’t know how practical
the implementation of that would be though. It might require linear types
along the lines of Rust in which case they would have to wait at least until
Swift has such a system.
>
>>
>>>> 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
>> [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]
https://lists.swift.org/mailman/listinfo/swift-evolution