Skip to content

Instantly share code, notes, and snippets.

@oleksii-demedetskyi
Created June 12, 2019 12:48
Show Gist options
  • Save oleksii-demedetskyi/f28171d4f2aac622c5d9b3d07000b117 to your computer and use it in GitHub Desktop.
Save oleksii-demedetskyi/f28171d4f2aac622c5d9b3d07000b117 to your computer and use it in GitHub Desktop.
Redux reducer composed using new @functionBuilder api
protocol Action {}
struct Reducer<State> {
let reduce: (State, Action) -> State
}
struct Increment: Action {}
struct Decrement: Action {}
func on<State, A>(_ actionType: A.Type, reduce: @escaping (State, A) -> State) -> Reducer<State> {
Reducer<State> { state, action in
guard let action = action as? A else {
return state
}
return reduce(state, action)
}
}
@_functionBuilder
struct ReduceBuilder<State> {
static func buildBlock(_ reducers: Reducer<State>...) -> Reducer<State> {
return Reducer<State> { state, action in
var state = state
for reducer in reducers {
state = reducer.reduce(state, action)
}
return state
}
}
}
func reduce<State>(@ReduceBuilder<State> builder: @escaping () -> Reducer<State>) -> Reducer<State> {
return builder()
}
let counter: Reducer<Int> = reduce {
on(Increment.self) { state, action in state + 1 }
on(Decrement.self) { state, action in state - 1 }
}
var state = 0
state = counter.reduce(state, Increment())
state = counter.reduce(state, Increment())
state = counter.reduce(state, Increment())
state = counter.reduce(state, Decrement())
state = counter.reduce(state, Decrement())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment