Guest User

Untitled

a guest
Apr 22nd, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.46 KB | None | 0 0
  1. //: [Previous](@previous)
  2.  
  3. import Foundation
  4.  
  5. protocol Changable {
  6. associatedtype Change
  7. mutating func apply(_ diff: Change)
  8. }
  9.  
  10. extension Array: Changable {
  11. enum Change {
  12. case insert(Element, at: Index)
  13. case remove(at: Index)
  14. }
  15.  
  16. mutating func apply(_ diff: Change) {
  17. switch diff {
  18. case let .insert(element, at: i):
  19. self.insert(element, at: i)
  20. case let .remove(at: i):
  21. self.remove(at: i)
  22. }
  23. }
  24. }
  25.  
  26. // what does filter do? we want to filter changes!
  27.  
  28. final class Box<A> where A: Changable {
  29. private(set) var value: A
  30. private var observers: [(Pending<A>) -> ()] = []
  31.  
  32. init(_ value: A) {
  33. self.value = value
  34. }
  35.  
  36. func change(_ change: A.Change) {
  37. let old = value
  38. value.apply(change)
  39. for o in observers {
  40. o(Pending(oldValue: old, change: change))
  41. }
  42. }
  43.  
  44. func map<B: Changable>(_ f: (A) -> (B, (Pending<A>) -> B.Change?)) -> Box<B> {
  45. let (initial, transform) = f(value)
  46. let result = Box<B>(initial)
  47. observers.append { pending in
  48. if let c = transform(pending) {
  49. result.change(c)
  50. }
  51. }
  52. return result
  53. }
  54.  
  55. func addObserver(_ o: @escaping (Pending<A>) -> ()) {
  56. observers.append(o)
  57. }
  58. }
  59.  
  60. struct Pending<A: Changable> {
  61. let oldValue: A
  62. let change: A.Change
  63. }
  64.  
  65. extension Array {
  66. fileprivate func filteredIndex(_ filterCond: (Element) -> Bool, at index: Int) -> Int {
  67. var result = 0
  68. guard index > 0 else { return 0 }
  69. for i in 0..<(index-1) {
  70. if !filterCond(self[i]) { result += 1 }
  71. }
  72. return result
  73. }
  74. func filtered(_ isIncluded: @escaping (Element) -> Bool) -> ([Element], (Pending<[Element]>) -> Change?) {
  75. let result = filter(isIncluded)
  76. return (result, { pending in
  77. switch pending.change {
  78. case let .insert(el, at: i):
  79. guard isIncluded(el) else { return nil }
  80. return .insert(el, at: pending.oldValue.filteredIndex(isIncluded, at: i)) // todo index
  81. case let .remove(at: i):
  82. guard isIncluded(pending.oldValue[i]) else { return nil }
  83. return .remove(at: i) // todo index
  84. }
  85. })
  86. }
  87. }
  88.  
  89. let x = Box([1,2,3,4])
  90. let y = x.map { $0.filtered { $0 % 2 == 0 }}
  91. y.addObserver {
  92. print($0)
  93. print(y.value)
  94. }
  95. y.value
  96. x.change(.insert(0, at: 4))
Add Comment
Please, Sign In to add comment