Skip to content

Instantly share code, notes, and snippets.

@twittemb
Last active April 6, 2023 08:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save twittemb/b4fe726554b7d61f60d81a1136b8e4a3 to your computer and use it in GitHub Desktop.
Save twittemb/b4fe726554b7d61f60d81a1136b8e4a3 to your computer and use it in GitHub Desktop.
// the State of the feedback loop
struct Levels {
let left: Int
let right: Int
}
// the transition requests of the feedback loop
enum Event {
case increaseLeft
case decreaseLeft
case increaseRight
case decreaseRight
}
// the side effects of the feedback loop
func leftEffect(inputLevels: Levels) -> AnyPublisher<Event, Never> {
// this is the stop condition to our Spin
guard inputLevels.left != inputLevels.right else { return Empty().eraseToAnyPublisher() }
// this is the regulation for the left level
if inputLevels.left < inputLevels.right {
return Just(.increaseLeft).eraseToAnyPublisher()
} else {
return Just(.decreaseLeft).eraseToAnyPublisher()
}
}
func rightEffect(inputLevels: Levels) -> AnyPublisher<Event, Never> {
// this is the stop condition to our Spin
guard inputLevels.left != inputLevels.right else { return Empty().eraseToAnyPublisher() }
// this is the regulation for the right level
if inputLevels.right < inputLevels.left {
return Just(.increaseRight).eraseToAnyPublisher()
} else {
return Just(.decreaseRight).eraseToAnyPublisher()
}
}
// the reducer of the feedback loop
func levelsReducer(currentLevels: Levels, event: Event) -> Levels {
guard currentLevels.left != currentLevels.right else { return currentLevels }
switch event {
case .decreaseLeft:
return Levels(left: currentLevels.left-1, right: currentLevels.right)
case .increaseLeft:
return Levels(left: currentLevels.left+1, right: currentLevels.right)
case .decreaseRight:
return Levels(left: currentLevels.left, right: currentLevels.right-1)
case .increaseRight:
return Levels(left: currentLevels.left, right: currentLevels.right+1)
}
}
// The builder way to build the Spin
let levelsSpin = Spinner
.initialState(Levels(left: 10, right: 20))
.feedback(Feedback(effect: leftEffect))
.feedback(Feedback(effect: rightEffect))
.reducer(Reducer(levelsReducer))
// The declarative way to build the Spin
let levelsSpin = CombineSpin(initialState: Levels(left: 10, right: 20),
reducer: Reducer(levelsReducer)) {
Feedback(effect: leftEffect)
Feedback(effect: rightEffect)
}
// to make a reactive stream from the Spin
AnyPublisher.stream(from: levelsSpin)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment