diff --git a/Sources/Verge/Store/Changes.swift b/Sources/Verge/Store/Changes.swift index f4b8b5faf9..389f361161 100644 --- a/Sources/Verge/Store/Changes.swift +++ b/Sources/Verge/Store/Changes.swift @@ -415,29 +415,14 @@ extension Changes { try takeIfChanged(compose, .equality()) } - /** - Performs a closure if the selected value changed from the previous one. - */ - @available(*, deprecated, message: "Use another function that returns IfChangedBox") - public func ifChanged( - _ selector: ChangesKeyPath, - _ comparer: some TypedComparator, - _ perform: (T) throws -> Result - ) rethrows -> Result? { - guard let value = takeIfChanged({ $0[keyPath: selector] }, comparer) else { - return nil - } - return try perform(value) - } - public func ifChanged( _ compose: (Value) -> Composed - ) -> IfChangedBox { + ) -> IfChangedBox { guard let result = takeIfChanged(compose) else { return .init() } - return .init(value: consume result) + return .init(value: consume result, source: innerBox) } /** @@ -451,23 +436,23 @@ extension Changes { */ public borrowing func ifChanged( _ compose: (borrowing Value) -> (repeat each Element) - ) -> IfChangedBox<(repeat each Element)> { + ) -> IfChangedBox { guard let result = _takeIfChanged_packed(compose) else { return .init() } - return .init(value: (repeat each result)) + return .init(value: (repeat each result), source: innerBox) } public borrowing func ifChanged( _ compose: (borrowing Value) -> (repeat each Element), comparator: some TypedComparator<(repeat each Element)> - ) -> IfChangedBox<(repeat each Element)> { + ) -> IfChangedBox { guard let result = _takeIfChanged_packed_nonEquatable(compose, comparator: comparator) else { return .init() } - return .init(value: (repeat each result)) + return .init(value: (repeat each result), source: innerBox) } /** @@ -475,7 +460,7 @@ extension Changes { */ public func ifChanged( _ keyPath: KeyPath - ) -> IfChangedBox { + ) -> IfChangedBox { ifChanged({ $0[keyPath: keyPath] }) } @@ -484,127 +469,10 @@ extension Changes { */ public func ifChanged( _ keyPaths: repeat KeyPath - ) -> IfChangedBox<(repeat each T)> { + ) -> IfChangedBox { ifChanged({ (repeat $0[keyPath: each keyPaths]) }) } - - - /** - Performs a closure if the selected value changed from the previous one. - */ - @available(*, deprecated, message: "Use another function that returns IfChangedBox") - public func ifChanged( - _ compose: (Value) -> Composed, - _ perform: (Composed) throws -> Result - ) rethrows -> Result? { - try ifChanged(compose, .equality(), perform) - } - - /** - Performs a closure if the selected value changed from the previous one. - */ - @inline(__always) - @available(*, deprecated, message: "Use another function that returns IfChangedBox") - public func ifChanged( - _ keyPath: ChangesKeyPath, - _ perform: (T) throws -> Result - ) rethrows -> Result? { - try ifChanged(keyPath, .equality(), perform) - } - - /** - Performs a closure if the selected value changed from the previous one. - Selected multiple value would be packed as tuple. - */ - @inline(__always) - @available(*, deprecated, message: "Use another function that returns IfChangedBox") - public func ifChanged( - _ keyPath0: ChangesKeyPath, - _ keyPath1: ChangesKeyPath, - _ perform: ((T0, T1)) throws -> Result - ) rethrows -> Result? { - try ifChanged({ ($0[keyPath: keyPath0], $0[keyPath: keyPath1]) as (T0, T1) }).do(perform) - } - - /** - Performs a closure if the selected value changed from the previous one. - Selected multiple value would be packed as tuple. - */ - @inline(__always) - @available(*, deprecated, message: "Use another function that returns IfChangedBox") - public func ifChanged( - _ keyPath0: ChangesKeyPath, - _ keyPath1: ChangesKeyPath, - _ keyPath2: ChangesKeyPath, - _ perform: ((T0, T1, T2)) throws -> Result - ) rethrows -> Result? { - try ifChanged( - { ($0[keyPath: keyPath0], $0[keyPath: keyPath1], $0[keyPath: keyPath2]) as (T0, T1, T2) } - ) - .do(perform) - } - - /** - Performs a closure if the selected value changed from the previous one. - Selected multiple value would be packed as tuple. - */ - @inline(__always) - @available(*, deprecated, message: "Use another function that returns IfChangedBox") - public func ifChanged( - _ keyPath0: ChangesKeyPath, - _ keyPath1: ChangesKeyPath, - _ keyPath2: ChangesKeyPath, - _ keyPath3: ChangesKeyPath, - _ perform: ((T0, T1, T2, T3)) throws -> Result - ) rethrows -> Result? { - try ifChanged( - { - ( - $0[keyPath: keyPath0], - $0[keyPath: keyPath1], - $0[keyPath: keyPath2], - $0[keyPath: keyPath3] - ) as (T0, T1, T2, T3) - } - ) - .do(perform) - } - - /** - Performs a closure if the selected value changed from the previous one. - Selected multiple value would be packed as tuple. - */ - @inline(__always) - @available(*, deprecated, message: "Use another function that returns IfChangedBox") - public func ifChanged< - T0: Equatable, - T1: Equatable, - T2: Equatable, - T3: Equatable, - T4: Equatable, - Result - >( - _ keyPath0: ChangesKeyPath, - _ keyPath1: ChangesKeyPath, - _ keyPath2: ChangesKeyPath, - _ keyPath3: ChangesKeyPath, - _ keyPath4: ChangesKeyPath, - _ perform: ((T0, T1, T2, T3, T4)) throws -> Result - ) rethrows -> Result? { - try ifChanged( - { - ( - $0[keyPath: keyPath0], - $0[keyPath: keyPath1], - $0[keyPath: keyPath2], - $0[keyPath: keyPath3], - $0[keyPath: keyPath4] - ) as (T0, T1, T2, T3, T4) - - } - ) - .do(perform) - } + } // MARK: - Has changes @@ -689,27 +557,27 @@ extension Changes where Value: Equatable { previousPrimitive != primitive } - @available(*, deprecated, message: "Use another function that returns IfChangedBox") - public func ifChanged(_ perform: (Value) throws -> Void) rethrows { - try ifChanged(\.self, perform) - } - - public func ifChanged() -> IfChangedBox { + public func ifChanged() -> IfChangedBox { ifChanged({ $0 }) } } -public struct IfChangedBox: ~Copyable { +public struct IfChangedBox: ~Copyable { public let value: T? + + @usableFromInline + let source: ReadonlyBox? - init(value: consuming T) { + init(value: consuming T, source: ReadonlyBox) { self.value = consume value + self.source = source } init() { - self.value = nil + self.value = nil + self.source = nil } @discardableResult @@ -720,5 +588,14 @@ public struct IfChangedBox: ~Copyable { } return nil } + + @discardableResult + @inlinable + public consuming func doWithSource(_ perform: (consuming ReadonlyBox) throws -> Return) rethrows -> Return? { + if let source { + return try perform(source) + } + return nil + } } diff --git a/Tests/VergeTests/ChangesTests.swift b/Tests/VergeTests/ChangesTests.swift index 57e6c0453c..0a2d6ca008 100644 --- a/Tests/VergeTests/ChangesTests.swift +++ b/Tests/VergeTests/ChangesTests.swift @@ -10,7 +10,7 @@ final class ChangesTests: XCTestCase { measure { for _ in 0..<1000 { - changes.ifChanged(\.name) { _ in + changes.ifChanged(\.name).do { _ in } } diff --git a/Tests/VergeTests/StateTypeTests.swift b/Tests/VergeTests/StateTypeTests.swift index 450deae2bf..5d69421e2c 100644 --- a/Tests/VergeTests/StateTypeTests.swift +++ b/Tests/VergeTests/StateTypeTests.swift @@ -40,7 +40,7 @@ final class StateTypeTests: XCTestCase { current: Changes ) { - current.ifChanged(\.count) { _ in + current.ifChanged(\.count).do { _ in modifying.count2 += 1 }