Thanks Brent. Was that real code?  :-)

If it was, I did not realize it was possible to do something like that in 
Swift. That seems very cool, attractive and powerful. It certainly would look 
much better with the sugary syntax. 

I can imagine building a collection of sort orderings like this for example. 

// Order by lastName asc, firstName asc
let orderings = Person.lastName.asc().then(.firstName.asc())

Don't know if it would be possible but I think it would be nice to be able to 
do it. The asc() method would create an ascending sort ordering and would 
establish Root as Person.  I wonder if it would be possible to have the then() 
know that Root is person so that its argument can be a key path relative to 
Person.  Or maybe this can be expressed differently if this is not the right 
way. 

Anyways, the sugary syntax looks very attractive IMHO. 

This is what my Java code looks like for something like that:

NSArray<EOSortOrdering> orderings = 
Person.LAST_NAME.asc().then(Person.FIRST_NAME.asc());

or this:

NSArray<EOSortOrdering> orderings = 
    new NSArray<>(
        Person.LAST_NAME.asc(),
        Person.FIRST_NAME.asc()
    );


> On Apr 1, 2017, at 10:24 PM, Brent Royal-Gordon <[email protected]> 
> wrote:
> 
> 
>>> On Apr 1, 2017, at 5:56 PM, Karl Wagner via swift-evolution 
>>> <[email protected]> wrote:
>>> 
>>> 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. 
>> 
>> Theoretically, you could do something like that with this proposal...
>> 
>> struct UnaryPredicate<Parameter, Result> {
>>     let evaluate: (Parameter) -> Result
>> }
>> struct BinaryPredicate<Left, Right, Result> {
>>     let evaluate: (Left, Right) -> Result
>> }
>> 
>> extension KeyPath where Value: Equatable {
>>     func equals(_ value: Value) -> UnaryPredicate<Root, Bool> {
>>         return UnaryPredicate { $0[keyPath: self] == value }
>>     }
>>     func equals<KP: KeyPath>(_ other: KP) -> BinaryPredicate<Root, KP.Root, 
>> Bool> where KP.Value == Value {
>>         return BinaryPredicate { $0[keyPath: self] == $1[keyPath: other] }
>>     }
>> }
>> 
>> let isDog = #keypath(Pet, .type).equals(.dog) // UnaryPredicate<Pet, Bool>
>> if isDog.evaluate(somePet) {
>>     print(“It’s a dog”)
>> }
>> 
>> let areSameLength = #keypath(Array<Int>, 
>> .count).equals(#keypath(Array<String>, .count))
>> // BinaryPredicate<Array<Int>, Array<String>, Bool>
>> if areSameLength.evaluate([1,2,3], [“a”, “b”, “c”]) {
>>     print(“same lengths”)
>> }
> 
> 
> You guys aren't thinking big enough.
> 
>       // This implementation is closure-based because it's too complex for an 
> email even *with* 
>       // generics system upgrades. Without type system upgrades, things get 
> *really* complicated, 
>       // though probably still tractable.
>       typealias Predicate<Element> = (Element) -> Bool
>       
>       func == <Root, Value: Equatable> (lhs: KeyPath<Root, Value>, rhs: 
> Value) -> Predicate<Root> {
>               return { $0[keyPath: lhs] == rhs }
>       }
>       
>       func < <Root, Value: Comparable> (lhs: KeyPath<Root, Value>, rhs: 
> Value) -> Predicate<Root> {
>               return { $0[keyPath: lhs] < rhs }
>       }
> 
>       func && <Root>(lhs: Predicate<Root>, rhs: Predicate<Root>) -> 
> Predicate<Root> {
>               return { lhs($0) && rhs($0) }
>       }
> 
>       extension KeyPath where Value: Collection {
>               func contains(where predicate: Predicate<Value.Element>) -> 
> Predicate<Value> {
>                       return { $0.contains(where: predicate) }
>               }
>       }
> 
> That gives you:
> 
>       let isPuppyQualifier = #keyPath(Pet, .type) == .dog && #keyPath(Pet, 
> .age) < 12
>       let familyQualifier = #keyPath(Family, .pets).contains(where: 
> isPuppyQualifier)
>       let familiesWithPuppies = Family.fetch(editingContext, familyQualifier)
> 
> Or, in one line with a more sugary syntax:
> 
>       let familiesWithPuppies = Family.fetch(editingContext, 
> (.pets).contains(where: .type == .dog && .age < 12))
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to