Guest User

Untitled

a guest
Dec 18th, 2017
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.37 KB | None | 0 0
  1. let flag: (Bool) -> String = { $0 ? "✅" : "❌" }
  2.  
  3. // ------------------------
  4. // Predicative
  5. // ------------------------
  6.  
  7. protocol Predicative {
  8. static func + (lhs: Self, rhs: Self) -> Self
  9. static func * (lhs: Self, rhs: Self) -> Self
  10. static func gt<P: PredicateLike>(_: P.Input) -> P where P.Input: Comparable, P.Output == Self
  11. static func lt<P: PredicateLike>(_: P.Input) -> P where P.Input: Comparable, P.Output == Self
  12. static func eq<P: PredicateLike>(_: P.Input) -> P where P.Input: Equatable, P.Output == Self
  13. static func or<P: PredicateLike>(_: P, _: P) -> P where P.Output == Self
  14. static func and<P: PredicateLike>(_: P, _: P) -> P where P.Output == Self
  15. static func run<P: PredicateLike>(_: P) -> (P.Input) -> Self where P.Output == Self
  16. }
  17.  
  18. extension Predicative {
  19.  
  20. static func or<P: PredicateLike>(_ p1: P, _ p2: P) -> P where P.Output == Self {
  21. return .init(p1, p2, *)
  22. }
  23.  
  24. static func and<P: PredicateLike>(_ p1: P, _ p2: P) -> P where P.Output == Self {
  25. return .init(p1, p2, +)
  26. }
  27.  
  28. static func run<P: PredicateLike>(_ p: P) -> (P.Input) -> Self where P.Output == Self {
  29. return p.run
  30. }
  31. }
  32.  
  33. // ------------------------
  34. // Predicate
  35. // ------------------------
  36.  
  37. protocol PredicateLike {
  38. associatedtype Input
  39. associatedtype Output: Predicative
  40.  
  41. init(_: Input, _: @escaping (Input, Input) -> Output)
  42. init(_: Self, _: Self, _: @escaping (Output, Output) -> Output)
  43.  
  44. func run(_ i: Input) -> Output
  45. }
  46.  
  47. extension PredicateLike {
  48.  
  49. static func leaf<P>(_ i: P.Input, _ b: @escaping (P.Input, P.Input) -> P.Output) -> P where P: PredicateLike {
  50. return .init(i, b)
  51. }
  52.  
  53. static func pred<P>(_ p1: P, _ p2: P, _ f: @escaping (P.Output, P.Output) -> P.Output) -> P where P: PredicateLike {
  54. return .init(p1, p2, f)
  55. }
  56.  
  57. static func or<P: PredicateLike>(_ p1: P, _ p2: P) -> P {
  58. return P.Output.or(p1, p2)
  59. }
  60.  
  61. static func and<P: PredicateLike>(_ p1: P, _ p2: P) -> P {
  62. return P.Output.and(p1, p2)
  63. }
  64.  
  65. static func lt<P: PredicateLike>(_ i: P.Input) -> P where P.Input: Comparable {
  66. return P.Output.lt(i)
  67. }
  68.  
  69. static func gt<P: PredicateLike>(_ i: P.Input) -> P where P.Input: Comparable {
  70. return P.Output.gt(i)
  71. }
  72.  
  73. static func eq<P: PredicateLike>(_ i: P.Input) -> P where P.Input: Equatable {
  74. return P.Output.eq(i)
  75. }
  76.  
  77. }
  78.  
  79. func || <P>(lhs: P, rhs: P) -> P where P: PredicateLike {
  80. return .or(lhs, rhs)
  81. }
  82.  
  83. func && <P>(lhs: P, rhs: P) -> P where P: PredicateLike {
  84. return .and(lhs, rhs)
  85. }
  86.  
  87. func gt<P: PredicateLike>(_ j: P.Input) -> P where P.Input: Comparable {
  88. return .gt(j)
  89. }
  90.  
  91. func lt<P: PredicateLike>(_ j: P.Input) -> P where P.Input: Comparable {
  92. return .lt(j)
  93. }
  94.  
  95. func eq<P: PredicateLike>(_ j: P.Input) -> P where P.Input: Equatable {
  96. return .eq(j)
  97. }
  98.  
  99. // ------------------------
  100. // PRED
  101. // ------------------------
  102.  
  103. enum Predicate<I, O: Predicative>: PredicateLike {
  104. typealias Input = I
  105. typealias Output = O
  106.  
  107. case _reduceLeaf(I, (I, I) -> O)
  108. indirect case _reducePred(Predicate, Predicate, (O, O) -> O)
  109.  
  110. init(_ i: Input, _ f: @escaping (Input, Input) -> Output) {
  111. self = ._reduceLeaf(i, f)
  112. }
  113.  
  114. init(_ p1: Predicate<I, O>, _ p2: Predicate<I, O>, _ f: @escaping (O, O) -> O) {
  115. self = ._reducePred(p1, p2, f)
  116. }
  117.  
  118. func run(_ i: I) -> O {
  119. switch self {
  120. case let ._reduceLeaf(j, reduce):
  121. return reduce(i, j)
  122. case let ._reducePred(p, q, reduce):
  123. return reduce(p.run(i), q.run(i))
  124. }
  125. }
  126. }
  127.  
  128. // ------------------------
  129. // Bool
  130. // ------------------------
  131.  
  132. extension Bool: Predicative {
  133.  
  134. static func + (lhs: Bool, rhs: Bool) -> Bool {
  135. return lhs && rhs
  136. }
  137. static func * (lhs: Bool, rhs: Bool) -> Bool {
  138. return lhs || rhs
  139. }
  140.  
  141. static func gt<P>(_ i: P.Input) -> P where P: PredicateLike, P.Input: Comparable, P.Output == Bool {
  142. return .leaf(i, >)
  143. }
  144.  
  145. static func lt<P>(_ i: P.Input) -> P where P: PredicateLike, P.Input: Comparable, P.Output == Bool {
  146. return .leaf(i, <)
  147. }
  148.  
  149. static func eq<P>(_ i: P.Input) -> P where P: PredicateLike, P.Input: Equatable, P.Output == Bool {
  150. return .leaf(i, ==)
  151. }
  152. }
  153.  
  154. // ------------------------
  155. // String
  156. // ------------------------
  157.  
  158. extension String: Predicative {
  159.  
  160. static func * (lhs: String, rhs: String) -> String {
  161. return lhs + " || " + rhs
  162. }
  163.  
  164. static func gt<P>(_ i: P.Input) -> P where P: PredicateLike, P.Input: Comparable, P.Output == String {
  165. return .leaf(i, { "\($0) > \($1)" })
  166. }
  167.  
  168. static func lt<P>(_ i: P.Input) -> P where P: PredicateLike, P.Input: Comparable, P.Output == String {
  169. return .leaf(i, { "\($0) < \($1)" })
  170. }
  171.  
  172. static func eq<P>(_ i: P.Input) -> P where P: PredicateLike, P.Input: Equatable, P.Output == String {
  173. return .leaf(i, { "\($0) == \($1)" })
  174. }
  175. }
  176.  
  177. // ------------------------
  178. // N
  179. // ------------------------
  180.  
  181. struct N: Predicative {
  182.  
  183. let s: String
  184. let b: Bool
  185.  
  186. static func + (lhs: N, rhs: N) -> N {
  187. return N(s: lhs.s + rhs.s, b: lhs.b + rhs.b)
  188. }
  189. static func * (lhs: N, rhs: N) -> N {
  190. return N(s: lhs.s * rhs.s, b: lhs.b * rhs.b)
  191. }
  192.  
  193. static func gt<P>(_ i: P.Input) -> P where P: PredicateLike, P.Input: Comparable, P.Output == N {
  194. return .leaf(i, { N(s:"(\($0) > \($1) [\(flag($0 > $1))])", b: $0 > $1) })
  195. }
  196.  
  197. static func lt<P>(_ i: P.Input) -> P where P: PredicateLike, P.Input: Comparable, P.Output == N {
  198. return .leaf(i, { N(s:"(\($0) < \($1) [\(flag($0 < $1))])", b: $0 < $1) })
  199. }
  200.  
  201. static func eq<P>(_ i: P.Input) -> P where P: PredicateLike, P.Input: Equatable, P.Output == N {
  202. return .leaf(i, { N(s:"(\($0) == \($1) [\(flag($0 == $1))])", b: $0 == $1) })
  203. }
  204. }
  205.  
  206. // ------------------------
  207. // Sequence
  208. // ------------------------
  209.  
  210. extension Sequence {
  211.  
  212. func filter(by: IPredicate<Element, Bool>) -> [Element] {
  213. return filter(by.run)
  214. }
  215.  
  216. func filter(by: IPredicate<Element, N>) -> String {
  217. return map { e in
  218. let n = by.run(e)
  219. return "\(flag(n.b)) \(e): \n " + n.s
  220. }.joined(separator: "\n ")
  221. }
  222. }
  223.  
  224. // ------------------------
  225. // IPredicate
  226. // ------------------------
  227.  
  228. struct IPredicate<I, O: Predicative> {
  229. let run: (I) -> O
  230.  
  231. init(_ f: @escaping (I) -> O) {
  232. self.run = f
  233. }
  234.  
  235. init<P>(_ target: KeyPath<I, P>, _ predicate: Predicate<P, O>) {
  236. run = { i in O.run(predicate)(i[keyPath: target]) }
  237. }
  238.  
  239. func liftD(_ ip: IPredicate<I, O>, _ f: @escaping (O, O) -> O) -> IPredicate<I, O> {
  240. return IPredicate { i in f(self.run(i), ip.run(i)) }
  241. }
  242. }
  243.  
  244. func == <R, I, P>(lhs: KeyPath<R, I>, rhs: Predicate<I, P>) -> IPredicate<R, P> where I: Comparable {
  245. return IPredicate(lhs, rhs)
  246. }
  247.  
  248. func && <I, O>(lhs: IPredicate<I, O>, rhs: IPredicate<I, O>) -> IPredicate<I, O> {
  249. return lhs.liftD(rhs, +)
  250. }
  251.  
  252. func || <I, O>(lhs: IPredicate<I, O>, rhs: IPredicate<I, O>) -> IPredicate<I, O> {
  253. return lhs.liftD(rhs, *)
  254. }
  255.  
  256. //// ------------------------
  257. //// Example
  258. //// ------------------------
  259.  
  260. struct P: CustomStringConvertible {
  261. let name: String
  262. let age: Int
  263. let address: A
  264. var description: String {
  265. return "P(name: \(name), age: \(age))"
  266. }
  267. }
  268.  
  269. struct A {
  270. let country: String
  271. }
  272.  
  273. let allPersons = [
  274. P(name: "a", age: 40, address: A(country: "🇨🇦")),
  275. P(name: "a", age: 31, address: A(country: "🇬🇧")),
  276. P(name: "b", age: 21, address: A(country: "🇩🇪")),
  277. P(name: "b", age: 50, address: A(country: "🇫🇷")),
  278. P(name: "c", age: 60, address: A(country: "🇯🇵"))
  279. ]
  280.  
  281. let result1: [P] = allPersons.filter(by:
  282. \.age == eq(40) || \.name == eq("a")
  283. )
  284.  
  285. let result2: String = allPersons.filter(by:
  286. \.age == eq(40) || \.name == eq("a")
  287. )
  288.  
  289. print(result2)
Add Comment
Please, Sign In to add comment