> On Mar 30, 2017, at 12:25 PM, Douglas Gregor via swift-evolution
> <[email protected]> wrote:
>
> Hello Swift community,
>
> 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:
>
> https://github.com/apple/swift-evolution/blob/master/proposals/0161-key-paths.md
>
> <https://github.com/apple/swift-evolution/blob/master/proposals/0161-key-paths.md>
> What is your evaluation of the proposal?
+ 1
> Is the problem being addressed significant enough to warrant a change to
> Swift?
It's a good start. Read below.
> Does this proposal fit well with the feel and direction of Swift?
Yes.
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.
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)
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:
let isPuppyQualifier = Pet.type.equals(.dog).and(Pet.age.lessThan(12))
let familiesQualifier = Family.pets.hasAtLeastOne(satisfying: isPuppyQualifier)
let familiesWithPuppies = Family.fetch(ec, familiesQualifier)
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.
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.
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.
> If you have used other languages or libraries with a similar feature, how do
> you feel that this proposal compares to those?
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.
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 similar to
this:
``` java
public static final KeyPath<String> FIRST_NAME = new
KeyPath<String>("firstName");
public static final KeyPath<String> LAST_NAME = new
KeyPath<String>("lastName");
public static final KeyPath<Date> BIRTH_DATE = new
KeyPath<Date>("birthDate");
```
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).
I then use key path objects to build sort orderings:
``` java
NSArray<EOSortOrdering> sortOrderings =
Person.FIRST_NAME.asc().then(Person.LAST_NAME.asc());
```
Or qualifiers to filter elements in an array:
``` java
personsOlderThan35 =
persons.filtered(Person.BIRTH_DATE.lessThan(thirtyFiveYearsAgo));
```
Or a qualifier for a query:
``` java
EOQualifier qualifier = Person.BIRTH_DATE.lessThan(thirtyFiveYearsAgo);
```
You can also build qualifiers that work across relationships, whether they are
to-one or to-many:
``` java
EOQualifier isPuppyQualifier =
Pet.TYPE.equals(PetType.DOG).and(Pet.AGE.lessThan(12))
// This qualifier could be used to fetch all the families that have puppies
EOQualifier qualifier =
Family.PETS.hasAtLeastOneObjectSatisfying(isPuppyQualifier);
NSArray<Family> familiesWithPuppies = Family.fetch(editingContext,
qualifier);
```
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.
>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.
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.
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.
For example, wouldn't it look much nicer if some day you could express the
above like this in Swift:
let isPuppyQualifier = Pet.type.equals(.dog).and(Pet.age.lessThan(12))
let familyQualifier = Family.pets.hasAtLeastOne(satisfying: isPuppyQualifier)
let familiesWithPuppies = Family.fetch(editingContext, familyQualifier)
For those unfamiliar with EOF, the editingContext in the code above is an
EOEditingContext which is analogous to NSManagedObjectContext.
> How much effort did you put into your review? A glance, a quick reading, or
> an in-depth study?
I've read just about every single reply in all threads related to Smart
KeyPaths, before and after the review period.
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution