<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 2 Apr 2017, at 02:56, Karl Wagner <<a href="mailto:karl.swift@springsup.com" class="">karl.swift@springsup.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class="">struct UnaryPredicate<Parameter> {</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class=""> let evaluate: (Parameter) -> Bool</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class="">}</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><font face="Courier" class="">struct BinaryPredicate<Left, Right> {</font></div></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><font face="Courier" class=""> let evaluate: (Left, Right) -> Bool</font></div></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><font face="Courier" class="">}</font></div></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class=""><br class=""></font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class="">extension KeyPath where Value: Equatable {</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class=""> func equals(_ value: Value) -> UnaryPredicate<Root> {</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class=""> return UnaryPredicate { $0[keyPath: self] == value }</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class=""> }</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><font face="Courier" class=""> func equals<KP: KeyPath>(_ other: KP) -> BinaryPredicate<Root, KP.Root> where KP.Value == Value {</font></div></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><font face="Courier" class=""> return BinaryPredicate { $0[keyPath: self] == $1[keyPath: other] }</font></div></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><font face="Courier" class=""> }</font></div></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class="">}</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class=""><br class=""></font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class="">let isDog = #keypath(Pet, .type).equals(.dog) // UnaryPredicate<Pet></font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class="">if isDog.evaluate(somePet) {</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class=""> print(“It’s a dog”)</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class="">}</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class="">let areSameLength = #keypath(Array<Int>, .count).equals(#keypath(Array<String>, .count))</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span class="" style="font-family: Courier;">// BinaryPredicate<Array<Int>, Array<String>></span></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class="">if areSameLength.evaluate([1,2,3], [“a”, “b”, “c”]) {</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class=""> print(“same lengths”)</font></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><font face="Courier" class="">}</font></div></div></blockquote></div><br class=""><div class=""><br class=""></div><div class="">Apologies, been working with lots of generic closures today and the ‘Result’ just came out instinctively. Of course the Result of a predicate is a Boolean…</div><div class=""><br class=""></div><div class="">Still, it’s useful to think about what some more advanced use-cases of keypaths might look like with this proposal. As far as syntax is concerned, operators may ultimately be the best way to make long predicate combinations cleaner.</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div style="text-align: left;" class=""><font face="Courier" class="">extension UnaryPredicate {</font></div><div style="text-align: left;" class=""><font face="Courier" class=""> static func &&<P>(left: UnaryPredicate<P>, right: UnaryPredicate<P>) -> UnaryPredicate<P> {</font></div><div style="text-align: left;" class=""><font face="Courier" class=""> return UnaryPredicate { self($0) && other($0) }</font></div><div style="text-align: left;" class=""><font face="Courier" class=""> }</font></div><div style="text-align: left;" class=""><font face="Courier" class="">}</font></div><div style="text-align: left;" class=""><font face="Courier" class=""><br class=""></font></div><div style="text-align: left;" class=""><font face="Courier" class="">let isHealthyPuppy = #keypath(Pet, .type).equals(.dog) && #keypath(Pet, .age).isLessThan(12) && #keypath(Pet, .health).equals(.good)</font></div><div style="text-align: left;" class=""><font face="Courier" class=""><br class=""></font></div><div style="text-align: left;" class=""><font face="Courier" class="">vs</font></div><div style="text-align: left;" class=""><font face="Courier" class=""><br class=""></font></div><div style="text-align: left;" class=""><font face="Courier" class="">let isHealthyPuppy = #keypath(Pet, .type).equals(.dog).and(#keypath(Pet, .age).isLessThan(12)).and(#keypath(Pet, .health).equals(.good))</font></div></blockquote><div class=""><br class=""></div><div class="">- Karl</div></body></html>