> 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