Skip to content
This repository has been archived by the owner on Dec 12, 2021. It is now read-only.

Refactor code by adding Effect, EffectQueue, Feedback #12

Merged
merged 1 commit into from
Jun 12, 2019

Conversation

inamiy
Copy link
Owner

@inamiy inamiy commented Jun 12, 2019

This PR brings quite a lot of improvements for effect handling including a bit of breaking changes.

New Features

1. Effect and EffectQueue (preferred)

enum Queue: EffectQueueProtocol {
    case request

    var flattenStrategy: FlattenStrategy {
        return .latest
    }
}

let mappings: [EffectMapping] = [
    .login    | .loggedOut  => .loggingIn  | Effect(loginOKProducer, queue: .request),
    .loginOK  | .loggingIn  => .loggedIn   | nil,
    .logout   | .loggedIn   => .loggingOut | Effect(logoutOKProducer, queue: .request),
    .logoutOK | .loggingOut => .loggedOut  | nil
]

automaton = Automaton(state: .loggedOut, inputs: signal, mapping: reduce(mappings))
  • Effect wraps a pure SignalProducer as a side-effect, and is also aware of which EffectQueue to be registered on.
  • EffectQueue is an Equatable enum to identify queues, which also associates with FlattenStrategy for flattening effects.
    • EffectQueue provides more flexible flattening strategies compared to previous ver 0.5.0 or Feedback systems.

2. Feedback (alternative approach found in ReactiveFeedback)

let mappings: [Mapping] = [
    .login    | .loggedOut  => .loggingIn,
    .loginOK  | .loggingIn  => .loggedIn,
    .logout   | .loggedIn   => .loggingOut,
    .logoutOK | .loggingOut => .loggedOut
]

automaton = Automaton(
    state: .loggedOut,
    inputs: signal,
    mapping: reduce(mappings),
    feedback: reduce([
        Feedback(
            filter: { $0.input == AuthInput.login },
            produce: { _ in loginOKProducer }
        ),
        Feedback(
            filter: { $0.input == AuthInput.logout },
            produce: { _ in logoutOKProducer }
        )
    ])
)

Compared to ReactiveFeedback, this feature includes:

  1. Feedback is isomorphic to Signal<(Input, FromState, ToState)> -> Signal<Input> which efficiently calculates next input from 3-tuple instead of 1 (ToState only as Moore Machine) or 2-tuple (Input and FromState as Mealy Machine).
    • This can be said as Moore-Mealy-hybrid machine!
  2. Cleanly separates inputs (hot signals) and feedback (cold producers)
  3. Reducible feedback via reduce.

Other breaking Changes

  • Introduced Initial Effect, same as Elm.Platform
  • (Slightly) Renamed some methods
  • When inputs send .completed, all running side-effects will be terminated immediately rather than waiting them to send final replies. This behavior will be same as send(.interrupted).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant