<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On May 27, 2016, at 5:37 PM, Anders Ha &lt;<a href="mailto:hello@andersio.co" class="">hello@andersio.co</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class="Apple-interchange-newline">On 28 May 2016, at 6:00 AM, Brent Royal-Gordon via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">I'm not sure how much metadata is necessary beyond name (in the key) and type (discussed soon).<br class=""></blockquote><br class="">In the future we may have user-defined attributes. &nbsp;It could be very useful to expose that.<br class=""></blockquote><br class=""><br class="">This is true.<br class=""><br class="">Actually, I'm wondering if property behaviors should be able to essentially declare alternate PropertyViews and add their properties to them. For instance:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>var behavior persistent&lt;Value: PersistentValue&gt;: Value where Self: ManagedObject {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>belongsto persistentProperties, static persistentInstanceProperties<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>name: String<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var value: Value<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>init() {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>value = entity.propertiesByName[name].defaultValue<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>get { return value }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>set { value = newValue }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>protocol Managed {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>static var persistentProperties: InstancePropertyView&lt;Self&gt; { get }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var persistentProperties: PropertyView&lt;Self&gt; { get set }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>...<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>class Person: Managed {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>@persistent var name: String<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>@persistent var birthDate: Date<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>print(Person.persistentProperties.keys)<span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// =&gt; "name", "birthDate"<br class=""><br class="">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.<br class=""><br class="">(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.)<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">Yes. I would hope that you could downcast a concrete lens:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let lens: () -&gt; inout Int = &amp;array.count<span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// Assuming this is a "get lens” syntax<br class=""></blockquote><br class="">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:<br class=""><br class="">let lens: (Array&lt;MyType&gt;) -&gt; Int = &amp;array.count<br class=""></blockquote><br class="">I envision there being both bound lenses (sorry, I forgot that `Array.count` isn't mutating):<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>struct Person { var name: String }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>var joe = Person(name: "Joe")<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let lens: () -&gt; inout String = &nbsp;&amp;joe.name<br class=""><br class="">And unbound ones:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let unboundLens: (inout Person) -&gt; inout String = Person.name<br class=""><br class="">`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.)<br class=""><br class="">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.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">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.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>It could be very useful be able to pass a lens bound to a value type as a nonescaping argument. &nbsp;The implementation would have to guarantee the bound lens can’t escape the effective scope of the value. &nbsp;I don’t know how practical the implementation of that would be though. &nbsp;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.</div><br class=""><blockquote type="cite" class=""><div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">And that you could later open the abstracted lens to get its concrete type:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>if let concreteLens = abstractLens openas Lens {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>print(Lens.ReturnValue)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>…<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""></blockquote><br class="">What about casting like this:<br class=""><br class="">let typedLens = abstractLens as? (Array&lt;MyType&gt;) -&gt; Int<br class=""></blockquote><br class="">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.<br class=""><br class="">--<span class="Apple-converted-space">&nbsp;</span><br class="">Brent Royal-Gordon<br class="">Architechies<br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></blockquote></div></blockquote></div><br class=""></body></html>