Advertisement
Guest User

Untitled

a guest
Jul 24th, 2017
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.68 KB | None | 0 0
  1. //: Playground - noun: a place where people can play
  2.  
  3. import Foundation
  4.  
  5. final class Disposable {
  6. private let dispose: () -> ()
  7. init(_ dispose: @escaping () -> ()) {
  8. self.dispose = dispose
  9. }
  10.  
  11. deinit {
  12. dispose()
  13. }
  14. }
  15.  
  16.  
  17. final class Ref<A> {
  18. typealias Observer = (A) -> ()
  19.  
  20. fileprivate let _get: () -> A
  21. fileprivate let _set: (A) -> ()
  22. private let _addObserver: (@escaping Observer) -> Disposable
  23.  
  24. var value: A {
  25. get {
  26. return _get()
  27. }
  28. set {
  29. _set(newValue)
  30. }
  31. }
  32.  
  33. init(get: @escaping () -> A, set: @escaping (A) -> (), addObserver: @escaping (@escaping Observer) -> Disposable) {
  34. _get = get
  35. _set = set
  36. _addObserver = addObserver
  37. }
  38.  
  39. func addObserver(observer: @escaping Observer) -> Disposable {
  40. return _addObserver(observer)
  41. }
  42. }
  43.  
  44. extension Ref {
  45. convenience init(initialValue: A) {
  46. var observers: [Int: Observer] = [:]
  47. var theValue = initialValue {
  48. didSet {
  49. observers.values.forEach { $0(theValue) }
  50. }
  51. }
  52. var freshId = (Int.min...).makeIterator()
  53. let get = { theValue }
  54. let set = { newValue in
  55. theValue = newValue
  56. }
  57. let addObserver = { (newObserver: @escaping Observer) -> Disposable in
  58. let id = freshId.next()!
  59. observers[id] = newObserver
  60. return Disposable {
  61. observers[id] = nil
  62. }
  63. }
  64. self.init(get: get, set: set, addObserver: addObserver)
  65. }
  66. }
  67.  
  68. extension Ref {
  69. subscript<B>(keyPath: WritableKeyPath<A,B>) -> Ref<B> {
  70. let parent = self
  71. return Ref<B>(get: { parent._get()[keyPath: keyPath] }, set: {
  72. var oldValue = parent.value
  73. oldValue[keyPath: keyPath] = $0
  74. parent._set(oldValue)
  75.  
  76. }, addObserver: { observer in
  77. parent.addObserver { observer($0[keyPath: keyPath]) }
  78. })
  79. }
  80. }
  81.  
  82. extension Ref where A: MutableCollection {
  83. subscript(index: A.Index) -> Ref<A.Element> {
  84. return Ref<A.Element>(get: { self._get()[index] }, set: { newValue in
  85. var old = self.value
  86. old[index] = newValue
  87. self._set(old)
  88. }, addObserver: { observer in
  89. self.addObserver { observer($0[index]) }
  90. })
  91. }
  92. }
  93.  
  94. struct History<A> {
  95. private let initialValue: A
  96. private var history: [A] = []
  97. private var redoStack: [A] = []
  98. var value: A {
  99. get {
  100. return history.last ?? initialValue
  101. }
  102. set {
  103. history.append(newValue)
  104. redoStack = []
  105. }
  106. }
  107.  
  108. init(initialValue: A) {
  109. self.initialValue = initialValue
  110. }
  111.  
  112. mutating func undo() {
  113. guard let item = history.popLast() else { return }
  114. redoStack.append(item)
  115. }
  116.  
  117. mutating func redo() {
  118. guard let item = redoStack.popLast() else { return }
  119. history.append(item)
  120. }
  121. }
  122.  
  123. struct Address {
  124. var street: String
  125. }
  126. struct Person {
  127. var name: String
  128. var addresses: [Address]
  129. }
  130.  
  131. typealias Addressbook = [Person]
  132.  
  133. let source: Ref<History<Addressbook>> = Ref(initialValue: History(initialValue: []))
  134. let addressBook: Ref<Addressbook> = source[\.value]
  135. addressBook.value.append(Person(name: "Test", addresses: []))
  136. addressBook[0].value.name = "New Name"
  137. print(addressBook[0].value)
  138. source.value.undo()
  139. print(addressBook[0].value)
  140. source.value.redo()
  141.  
  142. var twoPeople: Ref<Addressbook> = Ref(initialValue:
  143. [Person(name: "One", addresses: []),
  144. Person(name: "Two", addresses: [])])
  145. let p0 = twoPeople[0]
  146. twoPeople.value.removeFirst()
  147. print(p0.value)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement