PartialCasePath
and AnyCasePath
?
#28
Replies: 7 comments 2 replies
-
Maybe you have a better idea for naming 🌚 Implementation of extension Reducer {
public func dismissOn<LocalAction>(_ paths: CasePathValueDetector<LocalAction>...) -> Reducer
where Action == ModalAction<LocalAction>, LocalAction: Equatable {
.combine(
self,
Reducer { state, action, environment in
guard case let .action(action) = action else { return .none}
for path in paths where path.is(action) {
return .value(.dismiss)
}
return .none
}
)
}
} |
Beta Was this translation helpful? Give feedback.
-
Maybe adding |
Beta Was this translation helpful? Give feedback.
-
In the meantime we think ad hoc code like you've written in |
Beta Was this translation helpful? Give feedback.
-
At first, I thought it would be possible to implement using protocols (like |
Beta Was this translation helpful? Give feedback.
-
Also P.S. Maybe consider moving this issue to Discussions tab, I guess that place fits sharing ideas more 🙂 |
Beta Was this translation helpful? Give feedback.
-
@stephencelis, any further thoughts about it? 🙂 In my codebase I updated the naming, but maybe you may recommend even more appropriate one public struct CaseMarker<Root> {
private let _matches: (Root) -> Bool
public func matches(_ value: Root) -> Bool {
_matches(value)
}
public init(matches: @escaping (Root) -> Bool) {
self._matches = matches
}
public init<Value>(
for casePath: CasePath<Root, Value>
) {
self.init { casePath.extract(from: $0).isNotNil }
}
}
public prefix func / <Root, Value>(
embed: @escaping (Value) -> Root
) -> CaseMarker<Root> {
return CaseMarker(for: /embed)
}
public prefix func / <Root>(
case: Root
) -> CaseMarker<Root> {
return CaseMarker(for: /`case`)
} Refreshing thoughts:
Draft implementation: public struct PartialCasePath<Root> {
private let _embed: (Any) -> Root?
private let _extract: (Root) -> Any?
public init(embed: @escaping (Any) -> Root?, extract: @escaping (Root) -> Any?) {
self._embed = embed
self._extract = extract
}
public func embed(_ value: Any) -> Root? {
self._embed(value)
}
public func extract(from root: Root) -> Any? {
self._extract(root)
}
public init<Value>(_ casePath: CasePath<Root, Value>) {
self.init(
embed: pipe(cast(to: Value.self), map(casePath.embed)),
extract: casePath.extract
)
}
}
func cast<T>(to type: T.Type = T.self) -> (Any) -> T? {
return { $0 as? T }
}
extension CasePath {
// probably can avoid force unwrapping by constructing CasePath<Root?, Value?>
// and providing a way to modify casePath at the call site. I think these transformations
// need further investigation
public init(_ partialCasePath: PartialCasePath<Root>) {
self.init(
embed: pipe(partialCasePath.embed, \.unsafelyUnwrapped),
extract: pipe(partialCasePath.extract(from:), { $0 as? Value }, \.unsafelyUnwrapped)
)
}
}
public prefix func / <Root, Value>(
embed: @escaping (Value) -> Root
) -> PartialCasePath<Root> {
return PartialCasePath(/embed)
}
public prefix func / <Root>(
case: Root
) -> PartialCasePath<Root> {
return PartialCasePath(/`case`)
} extension Reducer {
public func dismissOn<LocalAction: Equatable>(
_ paths: PartialCasePath<LocalAction>...
) -> Reducer where Action == ModalAction<LocalAction> {
.combine(
self,
Reducer { state, action, environment in
guard case let .action(action) = action else { return .none }
return paths.contains { $0.extract(from: action).isNotNil }
? Effect(value: .dismiss)
: .none
}
)
}
} |
Beta Was this translation helpful? Give feedback.
-
Also, I remember #27 (comment), where you mentioned that CasePath is a struct so it has some limitations, but maybe it is worth making it a class with some inheritance? It's a major breaking change, and there are a lot of things to think of like naming ( |
Beta Was this translation helpful? Give feedback.
-
I'm using a type, called
CasePathValueDetector
which can detect if the case is an expected case, but it erases the Value type from CasePath to enable me to use arrays of CasePath for cases with different associated valueswith TCA to enable
dismissOn
higher order reducer for handling modals in UIKit (but it may usefull for creating generalized.on(_ action: Action, _ reduce: (inout State, Action, Environment) -> Effect) -> Reducer
reducer for example)it does the same as
but the second example has no associated values so I can just pass enum cases.
Method's signatures are
Beta Was this translation helpful? Give feedback.
All reactions