<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></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 Mar 30, 2017, at 12:25 PM, Douglas Gregor via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">Hello Swift community,</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class="">The review of SE-0161 "Smart KeyPaths: Better Key-Value Coding for Swift" begins now and runs through April 5, 2017. The proposal is available here:</p><blockquote style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 1em; border-left-width: 0.25em; border-left-style: solid; border-left-color: rgb(223, 226, 229); background-color: rgb(255, 255, 255);" class=""><div style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#6a737d" face="-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol" size="3" class=""><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0161-key-paths.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0161-key-paths.md</a></font></div></blockquote><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""><li style="box-sizing: border-box;" class="">What is your evaluation of the proposal?</li></ul></div></div></blockquote><div><br class=""></div>+ 1</div><div><br class=""></div><div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""><li style="box-sizing: border-box; margin-top: 0.25em;" class="">Is the problem being addressed significant enough to warrant a change to Swift?</li></ul></div></div></blockquote>It's a good start. Read below.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""><li style="box-sizing: border-box; margin-top: 0.25em;" class="">Does this proposal fit well with the feel and direction of Swift?</li></ul></div></div></blockquote>Yes.</div><div><br class=""></div><div>I just wished we could come up with a more elegant notation than #keyPath(Root, path). But I understand that just about all the special characters suggested are taken or reserved, i.e. $, ::, #, @. I favored the original syntax before the review period. If you keep reading you'll understand why.</div><div><br class=""></div><div>The only other alternative I can think of would be to rename the existing #keyPath() to #objcKeyPath() and make #keyPath() exclusive to swift key paths. But it's probably not much of an improvement over #keyPath(Root, path). In fact, if we wanted to get the key path of a static member then I think the proposed syntax would be better, i.e. #keyPath(Root.Type, staticMember)</div><div><br class=""></div><div>My goal would be to be able to extend these smart keys some day and use them with a object-to-relational-mapping module in Swift. I would love to be able to construct orderings, qualifiers for my queries with code that looked like this:</div><div><br class=""></div><div><div class=""><font face="Monaco" style="font-size: 12px;" class="">let isPuppyQualifier = Pet.type.equals(.dog).and(Pet.age.lessThan(12))</font></div><div class=""><font face="Monaco" style="font-size: 12px;" class="">let familiesQualifier = Family.pets.hasAtLeastOne(satisfying: isPuppyQualifier)</font></div><div class=""><font face="Monaco" style="font-size: 12px;" class="">let familiesWithPuppies = Family.fetch(ec, </font><span style="font-family: Monaco; font-size: 12px;" class="">familiesQualifier</span><font face="Monaco" style="font-size: 12px;" class="">)</font></div><div class=""><br class=""></div></div><div>I believe that in order to be able to use them like this, they would have to be extensible and use this notation. They would also have to be converted to strings. The reason is that the string can be used in combination with an object model to figure out the columns to use when building SQL.</div><div><br class=""></div><div>I don't know if Swift will evolve smart key paths in this direction, but it's an area that I think is begging for improvement compared to other languages that I use. I think Swift could make a difference. It would certainly attract a large number of developers working on the server side writing this type of code on a day to day basis. </div><div><br class=""></div><div>Having a very elegant object-to-relational-mapping module is very important. I really hope that Apple enables it and someone whether Apple or a third party is able to create something as nice as WebObjects and the Enterprise Objects Framework.</div><div><br class=""></div><div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""><li style="box-sizing: border-box; margin-top: 0.25em;" class="">If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?</li></ul></div></div></blockquote><div>I have used key paths in java / WebObjects. WebObjects is a really nice java-based library from Apple that originated in Objective-C during the NeXT era. It has key-value-coding and an Enterprise Objects Framework (which Craig Federighi helped design while at NeXT). It is similar to CoreData but it can connect to just about every database out there. Project Wonder has enhanced the experience and added source code generation from object models. </div><div><br class=""></div><div>The code generated from the object models has keys and key paths that contain string information as well as some type information similar to these smart key paths being proposed by SE-0161. The java code for these keys looks <i class="">similar</i> to this: </div><div><br class=""></div><div>``` java</div><div><br class=""></div><div><font face="Monaco" class=""><span style="font-size: 12px;" class=""> public static final KeyPath<String> FIRST_NAME = new KeyPath<String>("firstName");</span></font></div><div><font face="Monaco" class=""><span style="font-size: 12px;" class=""> public static final KeyPath<String> LAST_NAME = new KeyPath<String>("lastName");</span></font></div><div><font face="Monaco" class=""><span style="font-size: 12px;" class=""> public static final KeyPath<Date> BIRTH_DATE = new KeyPath<Date>("birthDate");</span></font></div><div>```</div><div><br class=""></div><div>For example, the above declarations are at the top of _Person.java class which is automatically generated from an object model. Person then extends _Person to get all the code automatically generated which includes getters and setters, i.e. lastName() and setLastName(value). </div><div><br class=""></div><div>I then use key path objects to build sort orderings:</div><div><br class=""></div><div>``` java</div><div><font face="Monaco" class=""><span style="font-size: 12px;" class=""> NSArray<EOSortOrdering> sortOrderings = Person.FIRST_NAME.asc().then(Person.LAST_NAME.asc());</span></font></div><div>```</div><div><br class=""></div><div>Or qualifiers to filter elements in an array:</div><div><br class=""></div><div>``` java</div><div><font face="Monaco" class=""><span style="font-size: 12px;" class=""> personsOlderThan35 = persons.filtered(Person.BIRTH_DATE.lessThan(thirtyFiveYearsAgo));</span></font></div><div>```</div><div><br class=""></div><div>Or a qualifier for a query:</div><div><br class=""></div><div><div>``` java</div><div><font face="Monaco" class=""><span style="font-size: 12px;" class=""> EOQualifier qualifier = Person.BIRTH_DATE.lessThan(thirtyFiveYearsAgo);</span></font></div><div>```</div><div class="">You can also build qualifiers that work across relationships, whether they are to-one or to-many:</div><div class=""><br class=""></div><div class=""><div>``` java</div><div><span class="Apple-tab-span" style="white-space:pre">        </span></div><div><font face="Monaco" class=""><span style="font-size: 12px;" class=""> EOQualifier isPuppyQualifier = Pet.TYPE.equals(PetType.DOG).and(Pet.AGE.lessThan(12))</span></font></div><div><font face="Monaco" class=""><span style="font-size: 12px;" class=""><br class=""></span></font></div><div><font face="Monaco" color="#00b800" class=""><span style="font-size: 12px;" class=""> // This qualifier could be used to fetch all the families that have puppies</span></font></div><div><font face="Monaco" class=""><span style="font-size: 12px;" class=""> EOQualifier qualifier = Family.PETS.hasAtLeastOneObjectSatisfying(isPuppyQualifier);</span></font></div><div><font face="Monaco" class=""><span style="font-size: 12px;" class=""> NSArray<Family> familiesWithPuppies = Family.fetch(editingContext, qualifier);</span></font></div><div>```</div></div><div class=""><br class=""></div><div class="">These key paths can be converted to strings and looked up in the object model. The object model has entities (EOEntity), attributes (EOAttribute), relationships (EORelationship), etc. They are roughly equivalent to NSEntityDescription, NSAttributeDescription and NSRelationshipDescription of CoreData.</div><div class=""><br class=""></div><div class="">From the keys in the key paths, the Enterprise Objects Framework (EOF) is able to look up in the entity the corresponding attributes of the same name and find the column name to which it is mapped in the database. This allows EOF to build the SQL. </div><div class=""><br class=""></div><div class="">I find WebObjects and Project Wonder solution very elegant, except for the ALL-CAPS notation used for the static constants that hold these keys with type information. </div><div class=""><br class=""></div><div class="">I wish CoreData (or similar object-to-relational-mapping module) in Swift eventually leverage smart keys and key paths to make our code beautiful when building sort orderings, qualifiers (predicates or whatever they are called in CoreData) to build queries or apply them in-memory to arrays. This is what I do every day.</div><div class=""><br class=""></div><div class="">For example, wouldn't it look much nicer if some day you could express the above like this in Swift:</div><div class=""><br class=""></div><div class=""><font face="Monaco" style="font-size: 12px;" class="">let isPuppyQualifier = Pet.type.equals(.dog).and(Pet.age.lessThan(12))</font></div><div class=""><font face="Monaco" style="font-size: 12px;" class="">let familyQualifier = Family.pets.hasAtLeastOne(satisfying: isPuppyQualifier)</font></div><div class=""><div class=""><font face="Monaco" style="font-size: 12px;" class="">let familiesWithPuppies = Family.fetch(editingContext, familyQualifier)</font></div></div><div class=""><div class=""><br class=""></div></div><div class="">For those unfamiliar with EOF, the <font face="Monaco" class=""><span style="font-size: 12px;" class="">editingContext</span></font> in the code above is an <font face="Monaco" class=""><span style="font-size: 12px;" class="">EOEditingContext</span></font> which is analogous to <font face="Monaco" class=""><span style="font-size: 12px;" class="">NSManagedObjectContext</span></font>. </div><div class=""><br class=""></div><div class=""><br class=""></div></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""><li style="box-sizing: border-box; margin-top: 0.25em;" class="">How much effort did you put into your review? A glance, a quick reading, or an in-depth study?</li></ul></div></div></blockquote></div>I've read just about every single reply in all threads related to Smart KeyPaths, before and after the review period.<div class=""><br class=""></div><div class=""><br class=""></div></body></html>