[][src]Struct froop::Imitator

pub struct Imitator<T: 'static> { /* fields omitted */ }

Imitators are used to create cyclic streams. Created by Stream::imitator().

Anatomy of an FRP app

cycle.js taught me one one way to structure an app built on FRP. A key ingredient are "cyclic streams".

  • A driver is something isolating communcation to the rest of thew world. This could be requests against an API, database or a UI.
  • Drivers are two-way communications.
  • An app is a main function that have driver input as argument and driver output as return value.
  • App input is called sources.
  • App output is called sinks.

These components would be in different files, but here's a distilled example:

use froop::{Stream, Sink};

enum DriverIn {
  // ... event type of input _from_ the driver.
}
#[derive(Clone)] // needed for imitate
enum DriverOut {
  // ... event type of output _to_ the driver.
}

// The driver, which also is a function.
fn my_driver(out: Stream<DriverOut>) -> Stream<DriverIn> {
    let sink = Stream::sink();

    // React to input from `out` and
    // produce output into `sink`.

    sink.stream()
}

// Input to the app_main from the drivers
struct AppSources {
    my_driver: Stream<DriverIn>,
}

// Output from the app_main to the drivers
struct AppSinks {
    my_driver: Stream<DriverOut>,
}

// The main function of the app
fn app_main(sources: AppSources) -> AppSinks {

    // React to input from the sources, and derive
    // output to the sinks. Produce an "app state".

    // This is just to make it compile. The output
    // would be derived from the app state.
    let my_driver_out = Stream::never();

    return AppSinks {
        my_driver: my_driver_out,
    }
}

// This function does what "cycle.js run" does (but in
// javascript it can be dynamic).
fn run() {
    // imitator to cycle back output from main
    let driver_out = Stream::imitator();

    // connect driver
    let driver_in = my_driver(driver_out.stream());

    // create sources for app main function
    let app_sources = AppSources {
        my_driver: driver_in,
    };

    // run main function
    let app_sinks = app_main(app_sources);

    // cycle back output to driver
    driver_out.imitate(&app_sinks.my_driver);
}

Methods

impl<T: Clone> Imitator<T>[src]

pub fn imitate(self, other: &Stream<T>) -> Subscription[src]

Start imitating another stream. This consumes the imitator since it can only imitate one other stream.

pub fn stream(&self) -> Stream<T>[src]

Get a stream of events from this imitator. One stream instance is created for each call, and they all receive the events from the imitated stream.

let imitator = froop::Stream::imitator();

let coll1 = imitator.stream().collect();
let coll2 = imitator.stream().collect();

let sink = froop::Stream::sink();
let stream = sink.stream();

imitator.imitate(&stream);

sink.update(42);
sink.end(); // imitator also ends here

assert_eq!(coll1.wait(), vec![42]);
assert_eq!(coll2.wait(), vec![42]);

Auto Trait Implementations

impl<T> Send for Imitator<T> where
    T: Send

impl<T> Sync for Imitator<T> where
    T: Send

Blanket Implementations

impl<T> From for T[src]

impl<T, U> Into for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom for T where
    U: Into<T>, 
[src]

type Error = !

🔬 This is a nightly-only experimental API. (try_from)

The type returned in the event of a conversion error.

impl<T> Borrow for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BorrowMut for T where
    T: ?Sized
[src]

impl<T, U> TryInto for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

🔬 This is a nightly-only experimental API. (try_from)

The type returned in the event of a conversion error.