From 64106c4d3d4ddba8c7bc2af75376e6d3d3d75601 Mon Sep 17 00:00:00 2001 From: Date: Mon, 29 Jun 2015 20:16:15 +0000 Subject: Update documentation --- carboxyl/index.html | 272 ++++++++++++++++++++++++++++++ carboxyl/lift/fn.lift0.html | 102 ++++++++++++ carboxyl/lift/fn.lift1.html | 102 ++++++++++++ carboxyl/lift/fn.lift2.html | 102 ++++++++++++ carboxyl/lift/fn.lift3.html | 102 ++++++++++++ carboxyl/lift/fn.lift4.html | 102 ++++++++++++ carboxyl/lift/index.html | 173 +++++++++++++++++++ carboxyl/lift/sidebar-items.js | 1 + carboxyl/macro.lift!.html | 119 +++++++++++++ carboxyl/pending/index.html | 0 carboxyl/pending/sidebar-items.js | 1 + carboxyl/readonly/index.html | 0 carboxyl/readonly/sidebar-items.js | 1 + carboxyl/sidebar-items.js | 1 + carboxyl/signal/index.html | 0 carboxyl/signal/sidebar-items.js | 1 + carboxyl/signal/struct.Signal.html | 10 ++ carboxyl/signal/struct.SignalMut.html | 10 ++ carboxyl/source/index.html | 0 carboxyl/source/sidebar-items.js | 1 + carboxyl/stream/index.html | 0 carboxyl/stream/sidebar-items.js | 1 + carboxyl/stream/struct.Sink.html | 10 ++ carboxyl/stream/struct.Stream.html | 10 ++ carboxyl/stream/trait.BoxClone.html | 0 carboxyl/struct.Signal.html | 245 +++++++++++++++++++++++++++ carboxyl/struct.SignalMut.html | 164 ++++++++++++++++++ carboxyl/struct.Sink.html | 172 +++++++++++++++++++ carboxyl/struct.Stream.html | 304 ++++++++++++++++++++++++++++++++++ carboxyl/transaction/index.html | 0 carboxyl/transaction/sidebar-items.js | 1 + 31 files changed, 2007 insertions(+) create mode 100644 carboxyl/index.html create mode 100644 carboxyl/lift/fn.lift0.html create mode 100644 carboxyl/lift/fn.lift1.html create mode 100644 carboxyl/lift/fn.lift2.html create mode 100644 carboxyl/lift/fn.lift3.html create mode 100644 carboxyl/lift/fn.lift4.html create mode 100644 carboxyl/lift/index.html create mode 100644 carboxyl/lift/sidebar-items.js create mode 100644 carboxyl/macro.lift!.html create mode 100644 carboxyl/pending/index.html create mode 100644 carboxyl/pending/sidebar-items.js create mode 100644 carboxyl/readonly/index.html create mode 100644 carboxyl/readonly/sidebar-items.js create mode 100644 carboxyl/sidebar-items.js create mode 100644 carboxyl/signal/index.html create mode 100644 carboxyl/signal/sidebar-items.js create mode 100644 carboxyl/signal/struct.Signal.html create mode 100644 carboxyl/signal/struct.SignalMut.html create mode 100644 carboxyl/source/index.html create mode 100644 carboxyl/source/sidebar-items.js create mode 100644 carboxyl/stream/index.html create mode 100644 carboxyl/stream/sidebar-items.js create mode 100644 carboxyl/stream/struct.Sink.html create mode 100644 carboxyl/stream/struct.Stream.html create mode 100644 carboxyl/stream/trait.BoxClone.html create mode 100644 carboxyl/struct.Signal.html create mode 100644 carboxyl/struct.SignalMut.html create mode 100644 carboxyl/struct.Sink.html create mode 100644 carboxyl/struct.Stream.html create mode 100644 carboxyl/transaction/index.html create mode 100644 carboxyl/transaction/sidebar-items.js (limited to 'carboxyl') diff --git a/carboxyl/index.html b/carboxyl/index.html new file mode 100644 index 0000000..345e4c3 --- /dev/null +++ b/carboxyl/index.html @@ -0,0 +1,272 @@ + + + + + + + + + + carboxyl - Rust + + + + + + + + + + + + + + + +
+

Crate carboxyl + + [] + + [src]

+

Carboxyl provides primitives for functional reactive programming in Rust. +It draws inspiration from the Sodium libraries and Push-Pull FRP, +as described by Elliott (2009).

+ +

Overview

+

Functional reactive programming (FRP) is a composable and modular +abstraction for creating dynamic and reactive systems. In its most general +form it models these systems as a composition of two basic primitives: +streams are a series of singular events and signals are continuously +changing values.

+ +

Carboxyl is an imperative, hybrid push- and pull-based implementation of +FRP. Streams and the discrete components of signals are data-driven, i.e. +whenever an event occurs the resulting changes are propagated to everything +that depends on it.

+ +

However, the continuous components of signals are demand-driven. Internally, +Carboxyl stores the state of a signal as a function. This function has to +be evaluated by consumers of a signal to obtain a concrete value.

+ +

Nonetheless, Carboxyl has no explicit notion of time. Its signals are +functions that can be evaluated at any time, but they do not carry any +inherent notion of time. Synchronization and atomicity is achieved by a +transaction system.

+ +

Functional reactive primitives

+

This library provides two basic types: Stream and Signal. A stream is a +discrete sequence of events, a signal is a container for values that change +(discretely) over time.

+ +

The FRP primitives are mostly implemented as methods of the basic types to +ease method chaining, except for the various lifting functions, as they do +not really belong to any type in particular.

+ +

In addition, the Sink type allows one to create a stream of events by +sending values into it. It is the only way to create a stream from scratch, +i.e. without using any of the other primitives.

+ +

Usage example

+

Here is a simple example of how you can use the primitives provided by +Carboxyl. First of all, events can be sent into a sink. From a sink one +can create a stream of events. Streams can also be filtered, mapped and +merged. One can e.g. hold the last event from a stream as a signal.

+
+use carboxyl::Sink;
+
+let sink = Sink::new();
+let stream = sink.stream();
+let signal = stream.hold(3);
+
+// The current value of the signal is initially 3
+assert_eq!(signal.sample(), 3);
+
+// When we fire an event, the signal get updated accordingly
+sink.send(5);
+assert_eq!(signal.sample(), 5);
+
+ +

One can also directly iterate over the stream instead of holding it in a +signal:

+
+let mut events = stream.events();
+sink.send(4);
+assert_eq!(events.next(), Some(4));
+
+ +

Streams and signals can be combined using various primitives. We can map a +stream to another stream using a function:

+
+let squares = stream.map(|x| x * x).hold(0);
+sink.send(4);
+assert_eq!(squares.sample(), 16);
+
+ +

Or we can filter a stream to create a new one that only contains events that +satisfy a certain predicate:

+
+let negatives = stream.filter(|&x| x < 0).hold(0);
+
+// This won't arrive at the signal.
+sink.send(4);
+assert_eq!(negatives.sample(), 0);
+
+// But this will!
+sink.send(-3);
+assert_eq!(negatives.sample(), -3);
+
+ +

There are some other methods on streams and signals, that you can find in +their respective APIs.

+ +

Note that all these objects are Send + Sync + Clone. This means you can +easily pass them around in your code, make clones, give them to another +thread, and they will still be updated correctly.

+ +

You may have noticed that certain primitives take a function as an argument. +There is a limitation on what kind of functions can and should be used here. +In general, as FRP provides an abstraction around mutable state, they should +be pure functions (i.e. free of side effects).

+ +

For the most part this is guaranteed by Rust's type system. A static +function with a matching signature always works. A closure though is very +restricted: it must not borrow its environment, as it is impossible to +satisfy the lifetime requirements for that. So you can only move stuff into +it from the environment. However, the moved contents of the closure may also +not be altered, which is guaranteed by the Fn(…) -> …) trait bound.

+ +

However, both closures and functions could still have side effects such as +I/O, changing mutable state via Mutex or RefCell, etc. While Rust's type +system cannot prevent this, you should generally not pass such functions to +the FRP primitives, as they break the benefits you get from using FRP. +(An exception here is debugging output.)

+

Modules

+ + + + + +
lift +

Lifting of n-ary functions.

+ +

Macros

+ + + + + +
lift! + +

Structs

+ + + + + + + + + + + + + + + + + + + + +
Signal +

A continuous signal that changes over time.

+ +
SignalMut +

Signal variant using inner mutability for efficient in-place updates.

+ +
Sink +

An event sink.

+ +
Stream +

A stream of events.

+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/lift/fn.lift0.html b/carboxyl/lift/fn.lift0.html new file mode 100644 index 0000000..f7fd88e --- /dev/null +++ b/carboxyl/lift/fn.lift0.html @@ -0,0 +1,102 @@ + + + + + + + + + + carboxyl::lift::lift0 - Rust + + + + + + + + + + + + + + + +
+

Function carboxyl::lift::lift0 + + [] + + [src]

+
pub fn lift0<A, F>(f: F) -> Signal<A> where F: Fn() -> A + Send + Sync + 'static

Lift a 0-ary function.

+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/lift/fn.lift1.html b/carboxyl/lift/fn.lift1.html new file mode 100644 index 0000000..5f7204d --- /dev/null +++ b/carboxyl/lift/fn.lift1.html @@ -0,0 +1,102 @@ + + + + + + + + + + carboxyl::lift::lift1 - Rust + + + + + + + + + + + + + + + +
+

Function carboxyl::lift::lift1 + + [] + + [src]

+
pub fn lift1<A, B, F>(f: F, sa: &Signal<A>) -> Signal<B> where A: Send + Sync + Clone + 'static, B: Send + Sync + Clone + 'static, F: Fn(A) -> B + Send + Sync + 'static

Lift a unary function.

+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/lift/fn.lift2.html b/carboxyl/lift/fn.lift2.html new file mode 100644 index 0000000..8fbae6d --- /dev/null +++ b/carboxyl/lift/fn.lift2.html @@ -0,0 +1,102 @@ + + + + + + + + + + carboxyl::lift::lift2 - Rust + + + + + + + + + + + + + + + +
+

Function carboxyl::lift::lift2 + + [] + + [src]

+
pub fn lift2<A, B, C, F>(f: F, sa: &Signal<A>, sb: &Signal<B>) -> Signal<C> where A: Send + Sync + Clone + 'static, B: Send + Sync + Clone + 'static, C: Send + Sync + Clone + 'static, F: Fn(A, B) -> C + Send + Sync + 'static

Lift a binary function.

+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/lift/fn.lift3.html b/carboxyl/lift/fn.lift3.html new file mode 100644 index 0000000..2501d07 --- /dev/null +++ b/carboxyl/lift/fn.lift3.html @@ -0,0 +1,102 @@ + + + + + + + + + + carboxyl::lift::lift3 - Rust + + + + + + + + + + + + + + + +
+

Function carboxyl::lift::lift3 + + [] + + [src]

+
pub fn lift3<F, A, B, C, Ret>(f: F, ca: &Signal<A>, cb: &Signal<B>, cc: &Signal<C>) -> Signal<Ret> where F: Fn(A, B, C) -> Ret + Send + Sync + 'static, A: Send + Sync + Clone + 'static, B: Send + Sync + Clone + 'static, C: Send + Sync + Clone + 'static, Ret: Send + Sync + Clone + 'static

Lift a ternary function.

+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/lift/fn.lift4.html b/carboxyl/lift/fn.lift4.html new file mode 100644 index 0000000..ca930a1 --- /dev/null +++ b/carboxyl/lift/fn.lift4.html @@ -0,0 +1,102 @@ + + + + + + + + + + carboxyl::lift::lift4 - Rust + + + + + + + + + + + + + + + +
+

Function carboxyl::lift::lift4 + + [] + + [src]

+
pub fn lift4<F, A, B, C, D, Ret>(f: F, ca: &Signal<A>, cb: &Signal<B>, cc: &Signal<C>, cd: &Signal<D>) -> Signal<Ret> where F: Fn(A, B, C, D) -> Ret + Send + Sync + 'static, A: Send + Sync + Clone + 'static, B: Send + Sync + Clone + 'static, C: Send + Sync + Clone + 'static, D: Send + Sync + Clone + 'static, Ret: Send + Sync + Clone + 'static

Lift a quarternary function.

+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/lift/index.html b/carboxyl/lift/index.html new file mode 100644 index 0000000..57f4038 --- /dev/null +++ b/carboxyl/lift/index.html @@ -0,0 +1,173 @@ + + + + + + + + + + carboxyl::lift - Rust + + + + + + + + + + + + + + + +
+

Module carboxyl::lift + + [] + + [src]

+

Lifting of n-ary functions.

+ +

A lift maps a function on values to a function on signals. Given a function of +type F: Fn(A, B, …) -> R and signals of types Signal<A>, Signal<B>, … the +lift! macro creates a Signal<R>, whose content is computed using the +function.

+ +

Currently lift is only implemented for functions with up to four arguments. +This limitation is due to the current implementation strategy (and maybe +limitations of Rust's type system), but it can be increased to arbitrary but +finite arity if required.

+ +

Example

+let sink_a = Sink::new();
+let sink_b = Sink::new();
+let product = lift!(
+    |a, b| a * b,
+    &sink_a.stream().hold(0),
+    &sink_b.stream().hold(0)
+);
+assert_eq!(product.sample(), 0);
+sink_a.send(3);
+sink_b.send(5);
+assert_eq!(product.sample(), 15);
+
+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + +
lift0 +

Lift a 0-ary function.

+ +
lift1 +

Lift a unary function.

+ +
lift2 +

Lift a binary function.

+ +
lift3 +

Lift a ternary function.

+ +
lift4 +

Lift a quarternary function.

+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/lift/sidebar-items.js b/carboxyl/lift/sidebar-items.js new file mode 100644 index 0000000..2b8d168 --- /dev/null +++ b/carboxyl/lift/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"fn":[["lift0","Lift a 0-ary function."],["lift1","Lift a unary function."],["lift2","Lift a binary function."],["lift3","Lift a ternary function."],["lift4","Lift a quarternary function."]]}); \ No newline at end of file diff --git a/carboxyl/macro.lift!.html b/carboxyl/macro.lift!.html new file mode 100644 index 0000000..a0d54e3 --- /dev/null +++ b/carboxyl/macro.lift!.html @@ -0,0 +1,119 @@ + + + + + + + + + + carboxyl::lift! - Rust + + + + + + + + + + + + + + + +
+

carboxyl::lift! + + [] + + [src]

+
+macro_rules! lift {
+    ($f: expr)
+        => ( $crate::lift::lift0($f) );
+
+    ($f: expr, $a: expr)
+        => ( $crate::lift::lift1($f, $a) );
+
+    ($f: expr, $a: expr, $b: expr)
+        => ( $crate::lift::lift2($f, $a, $b) );
+
+    ($f: expr, $a: expr, $b: expr, $c: expr)
+        => ( $crate::lift::lift3($f, $a, $b, $c) );
+
+    ($f: expr, $a: expr, $b: expr, $c: expr, $d: expr)
+        => ( $crate::lift::lift4($f, $a, $b, $c, $d) );
+}
+
+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/pending/index.html b/carboxyl/pending/index.html new file mode 100644 index 0000000..e69de29 diff --git a/carboxyl/pending/sidebar-items.js b/carboxyl/pending/sidebar-items.js new file mode 100644 index 0000000..48333d3 --- /dev/null +++ b/carboxyl/pending/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({}); \ No newline at end of file diff --git a/carboxyl/readonly/index.html b/carboxyl/readonly/index.html new file mode 100644 index 0000000..e69de29 diff --git a/carboxyl/readonly/sidebar-items.js b/carboxyl/readonly/sidebar-items.js new file mode 100644 index 0000000..48333d3 --- /dev/null +++ b/carboxyl/readonly/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({}); \ No newline at end of file diff --git a/carboxyl/sidebar-items.js b/carboxyl/sidebar-items.js new file mode 100644 index 0000000..55a962e --- /dev/null +++ b/carboxyl/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"macro":[["lift!",""]],"mod":[["lift","Lifting of n-ary functions."]],"struct":[["Signal","A continuous signal that changes over time."],["SignalMut","Signal variant using inner mutability for efficient in-place updates."],["Sink","An event sink."],["Stream","A stream of events."]]}); \ No newline at end of file diff --git a/carboxyl/signal/index.html b/carboxyl/signal/index.html new file mode 100644 index 0000000..e69de29 diff --git a/carboxyl/signal/sidebar-items.js b/carboxyl/signal/sidebar-items.js new file mode 100644 index 0000000..452ea30 --- /dev/null +++ b/carboxyl/signal/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["Signal","A continuous signal that changes over time."],["SignalMut","Signal variant using inner mutability for efficient in-place updates."]]}); \ No newline at end of file diff --git a/carboxyl/signal/struct.Signal.html b/carboxyl/signal/struct.Signal.html new file mode 100644 index 0000000..34bb4ea --- /dev/null +++ b/carboxyl/signal/struct.Signal.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../carboxyl/struct.Signal.html...

+ + + \ No newline at end of file diff --git a/carboxyl/signal/struct.SignalMut.html b/carboxyl/signal/struct.SignalMut.html new file mode 100644 index 0000000..9a55706 --- /dev/null +++ b/carboxyl/signal/struct.SignalMut.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../carboxyl/struct.SignalMut.html...

+ + + \ No newline at end of file diff --git a/carboxyl/source/index.html b/carboxyl/source/index.html new file mode 100644 index 0000000..e69de29 diff --git a/carboxyl/source/sidebar-items.js b/carboxyl/source/sidebar-items.js new file mode 100644 index 0000000..48333d3 --- /dev/null +++ b/carboxyl/source/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({}); \ No newline at end of file diff --git a/carboxyl/stream/index.html b/carboxyl/stream/index.html new file mode 100644 index 0000000..e69de29 diff --git a/carboxyl/stream/sidebar-items.js b/carboxyl/stream/sidebar-items.js new file mode 100644 index 0000000..ccdbbe7 --- /dev/null +++ b/carboxyl/stream/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["Sink","An event sink."],["Stream","A stream of events."]],"trait":[["BoxClone","Trait to wrap cloning of boxed values in a object-safe manner"]]}); \ No newline at end of file diff --git a/carboxyl/stream/struct.Sink.html b/carboxyl/stream/struct.Sink.html new file mode 100644 index 0000000..97044fd --- /dev/null +++ b/carboxyl/stream/struct.Sink.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../carboxyl/struct.Sink.html...

+ + + \ No newline at end of file diff --git a/carboxyl/stream/struct.Stream.html b/carboxyl/stream/struct.Stream.html new file mode 100644 index 0000000..9c8a019 --- /dev/null +++ b/carboxyl/stream/struct.Stream.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../carboxyl/struct.Stream.html...

+ + + \ No newline at end of file diff --git a/carboxyl/stream/trait.BoxClone.html b/carboxyl/stream/trait.BoxClone.html new file mode 100644 index 0000000..e69de29 diff --git a/carboxyl/struct.Signal.html b/carboxyl/struct.Signal.html new file mode 100644 index 0000000..16abc52 --- /dev/null +++ b/carboxyl/struct.Signal.html @@ -0,0 +1,245 @@ + + + + + + + + + + carboxyl::Signal - Rust + + + + + + + + + + + + + + + +
+

Struct carboxyl::Signal + + [] + + [src]

+
pub struct Signal<A> {
+    // some fields omitted
+}

A continuous signal that changes over time.

+ +

Signals can be thought of as values that change over time. They have both a +continuous and a discrete component. This means that their current value is +defined by a function that can be called at any time. That function is only +evaluated on-demand, when the signal's current value is sampled. (This is +also called pull semantics in the literature on FRP.)

+ +

In addition, the current function used to sample a signal may change +discretely in reaction to some event. For instance, it is possible to create +a signal from an event stream, by holding the last event occurence as the +current value of the stream.

+ +

Algebraic laws

+

Signals come with some primitive methods to compose them with each other and +with streams. Some of these primitives give the signals an algebraic +structure.

+ +

Functor

+

Signals form a functor under unary lifting. Thus, the following laws hold:

+ + + +

Applicative functor

+

By extension, using the notion of a signal of a function, signals also +become an applicative using Signal::new as pure and +|sf, sa| lift!(|f, a| f(a), &sf, &sa) as <*>.

+ +

TODO: Expand on this and replace the Haskell reference.

+

Methods

impl<A: Clone + 'static> Signal<A>

fn new(a: A) -> Signal<A>

+

Create a constant signal.

+

fn sample(&self) -> A

+

Sample the current value of the signal.

+

impl<A: Clone + Send + Sync + 'static> Signal<A>

fn cyclic<F>(def: F) -> Signal<A> where F: FnOnce(&Signal<A>) -> Signal<A>

+

Create a signal with a cyclic definition.

+ +

The closure gets an undefined forward-declaration of a signal. It is +supposed to return a self-referential definition of the same signal.

+ +

Sampling the forward-declared signal, before it is properly defined, +will cause a run-time panic.

+ +

This pattern is useful to implement accumulators, counters and other +loops that depend on the sampling behaviour of a signal before a +transaction.

+

fn snapshot<B, C, F>(&self, stream: &Stream<B>, f: F) -> Stream<C> where B: Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, F: Fn(A, B) -> C + Send + Sync + 'static

+

Combine the signal with a stream in a snapshot.

+ +

snapshot creates a new stream given a signal and a stream. Whenever +the input stream fires an event, the output stream fires an event +created from the signal's current value and that event using the +supplied function.

+
+let sink1: Sink<i32> = Sink::new();
+let sink2: Sink<f64> = Sink::new();
+let mut events = sink1.stream().hold(1)
+    .snapshot(&sink2.stream(), |a, b| (a, b))
+    .events();
+
+// Updating its signal does not cause the snapshot to fire
+sink1.send(4);
+
+// However sending an event down the stream does
+sink2.send(3.0);
+assert_eq!(events.next(), Some((4, 3.0)));
+
+

impl<A: Clone + Send + Sync + 'static> Signal<Signal<A>>

fn switch(&self) -> Signal<A>

+

Switch between signals.

+ +

This transforms a Signal<Signal<A>> into a Signal<A>. The nested +signal can be thought of as a representation of a switch between different +input signals, that allows one to change the structure of the dependency +graph at run-time. switch provides a way to access the inner value of +the currently active signal.

+ +

The following example demonstrates how to use this to switch between two +input signals based on a Button event stream:

+
+// Button type
+#[derive(Clone, Show)]
+enum Button { A, B };
+
+// The input sinks
+let sink_a = Sink::<i32>::new();
+let sink_b = Sink::<i32>::new();
+
+// The button sink
+let sink_button = Sink::<Button>::new();
+
+// Create the output
+let output = {
+
+    // Hold input sinks in a signal with some initials
+    let channel_a = sink_a.stream().hold(1);
+    let channel_b = sink_b.stream().hold(2);
+
+    // A trivial default channel used before any button event
+    let default_channel = Sink::new().stream().hold(0);
+
+    // Map button to the channel signals, hold with the default channel as
+    // initial value and switch between the signals
+    sink_button
+        .stream()
+        .map(move |b| match b {
+            Button::A => channel_a.clone(),
+            Button::B => channel_b.clone(),
+        })
+        .hold(default_channel)
+        .switch()
+};
+
+// In the beginning, output will come from the default channel
+assert_eq!(output.sample(), 0);
+
+// Let's switch to channel A
+sink_button.send(Button::A);
+assert_eq!(output.sample(), 1);
+
+// And to channel B
+sink_button.send(Button::B);
+assert_eq!(output.sample(), 2);
+
+// The channels can change, too, of course
+for k in 4..13 {
+    sink_b.send(k);
+    assert_eq!(output.sample(), k);
+}
+sink_button.send(Button::A);
+for k in 21..77 {
+    sink_a.send(k);
+    assert_eq!(output.sample(), k);
+}
+
+

Trait Implementations

impl<A> Clone for Signal<A>

fn clone(&self) -> Signal<A>

+

fn clone_from(&mut self, source: &Self)

+

impl<A: Debug + Clone + 'static> Debug for Signal<A>

fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error>

+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/struct.SignalMut.html b/carboxyl/struct.SignalMut.html new file mode 100644 index 0000000..884baec --- /dev/null +++ b/carboxyl/struct.SignalMut.html @@ -0,0 +1,164 @@ + + + + + + + + + + carboxyl::SignalMut - Rust + + + + + + + + + + + + + + + +
+

Struct carboxyl::SignalMut + + [] + + [src]

+
pub struct SignalMut<A> {
+    // some fields omitted
+}

Signal variant using inner mutability for efficient in-place updates.

+ +

This is the only kind of primitive that allows non-Clone types to be +wrapped into functional reactive abstractions. The API is somewhat different +from that of a regular signal to accommodate this.

+ +

One cannot directly sample a SignalMut as this would require a clone. +Instead it comes with a couple of adaptor methods that mimick a subset of +the Signal API. However, all functions passed to these methods take the +argument coming from the SignalMut by reference.

+

Methods

impl<A: Send + Sync + 'static> SignalMut<A>

fn snapshot<B, C, F>(&self, stream: &Stream<B>, f: F) -> Stream<C> where B: Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, F: Fn(&A, B) -> C + Send + Sync + 'static

+

Semantically the same as Signal::snapshot

+ +

The key difference here is, that the combining function takes its first +argument by reference, as it can't be moved out of the SignalMut.

+ +

Example

+let sink1 = Sink::new();
+let sink2 = Sink::new();
+// Collect values in a mutable `Vec`
+let values = sink1.stream().scan_mut(vec![], |v, a| v.push(a));
+// Snapshot some value from it
+let mut index = values.snapshot(&sink2.stream(),
+    |v, k| v.get(k).map(|x| *x)
+).events();
+
+sink1.send(4);
+sink1.send(5);
+sink2.send(0);
+assert_eq!(index.next(), Some(Some(4)));
+
+sink2.send(1);
+assert_eq!(index.next(), Some(Some(5)));
+
+sink2.send(2);
+assert_eq!(index.next(), Some(None));
+
+

fn combine<B, C, F>(&self, signal: &Signal<B>, f: F) -> Signal<C> where B: Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, F: Fn(&A, B) -> C + Send + Sync + 'static

+

Similar to lift2. Combines a SignalMut with a Signal using a +function. The function takes its first argument by reference.

+

fn combine_mut<B, C, F>(&self, other: &SignalMut<B>, f: F) -> Signal<C> where B: Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, F: Fn(&A, &B) -> C + Send + Sync + 'static

+

Similar to lift2, but combines two SignalMut using a function. The +supplied function takes both arguments by reference.

+ +

Example

+let sink: Sink<i32> = Sink::new();
+let sum = sink.stream().scan_mut(0, |sum, a| *sum += a);
+let product = sink.stream().scan_mut(1, |prod, a| *prod *= a);
+let combo = sum.combine_mut(&product, |s, p| (*s, *p));
+
+sink.send(1);
+assert_eq!(combo.sample(), (1, 1));
+
+sink.send(3);
+assert_eq!(combo.sample(), (4, 3));
+
+sink.send(5);
+assert_eq!(combo.sample(), (9, 15));
+
+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/struct.Sink.html b/carboxyl/struct.Sink.html new file mode 100644 index 0000000..742e070 --- /dev/null +++ b/carboxyl/struct.Sink.html @@ -0,0 +1,172 @@ + + + + + + + + + + carboxyl::Sink - Rust + + + + + + + + + + + + + + + +
+

Struct carboxyl::Sink + + [] + + [src]

+
pub struct Sink<A> {
+    // some fields omitted
+}

An event sink.

+ +

This primitive is a way of generating streams of events. One can send +input values into a sink and generate a stream that fires all these inputs +as events:

+
+// A new sink
+let sink = Sink::new();
+
+// Make an iterator over a stream.
+let mut events = sink.stream().events();
+
+// Send a value into the sink
+sink.send(5);
+
+// The stream
+assert_eq!(events.next(), Some(5));
+
+ +

You can also feed a sink with an iterator:

+
+sink.feed(20..40);
+assert_eq!(events.take(4).collect::<Vec<_>>(), vec![20, 21, 22, 23]);
+
+ +

Asynchronous calls

+

It is possible to send events into the sink asynchronously using the methods +send_async and feed_async. Note though, that this will void some +guarantees on the order of events. In the following example, it is unclear, +which event is the first in the stream:

+
+let sink = Sink::new();
+let mut events = sink.stream().events();
+sink.send_async(13);
+sink.send_async(22);
+let first = events.next().unwrap();
+assert!(first == 13 || first == 22);
+
+ +

feed_async provides a workaround, as it preserves the order of events from +the iterator. However, any event sent into the sink after a call to it, may +come at any point between the iterator events.

+

Methods

impl<A: Send + Sync> Sink<A>

fn new() -> Sink<A>

+

Create a new sink.

+

fn stream(&self) -> Stream<A>

+

Generate a stream that fires all events sent into the sink.

+

impl<A: Send + Sync + Clone + 'static> Sink<A>

fn send_async(&self, a: A)

+

Asynchronous send.

+ +

Same as send, but it spawns a new thread to process the updates to +dependent streams and signals.

+

fn feed<I: IntoIterator<Item=A>>(&self, iterator: I)

+

Feed values from an iterator into the sink.

+ +

This method feeds events into the sink from an iterator.

+

fn feed_async<I: IntoIterator<Item=A> + Send + 'static>(&self, iterator: I)

+

Asynchronous feed.

+ +

This is the same as feed, but it does not block, since it spawns the +feeding as a new task. This is useful, if the provided iterator is large +or even infinite (e.g. an I/O event loop).

+

fn send(&self, a: A)

+

Send a value into the sink.

+ +

When a value is sent into the sink, an event is fired in all dependent +streams.

+

Trait Implementations

impl<A> Clone for Sink<A>

fn clone(&self) -> Sink<A>

+

fn clone_from(&mut self, source: &Self)

+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/struct.Stream.html b/carboxyl/struct.Stream.html new file mode 100644 index 0000000..e51f5ac --- /dev/null +++ b/carboxyl/struct.Stream.html @@ -0,0 +1,304 @@ + + + + + + + + + + carboxyl::Stream - Rust + + + + + + + + + + + + + + + +
+

Struct carboxyl::Stream + + [] + + [src]

+
pub struct Stream<A> {
+    // some fields omitted
+}

A stream of events.

+ +

Conceptually a stream can be thought of as a series of discrete events that +occur at specific times. They are ordered by a transaction system. This +means that firings of disjoint events can not interfere with each other. The +consequences of one event are atomically reflected in dependent quantities.

+ +

Streams provide a number of primitive operations. These can be used to +compose streams and combine them with signals. For instance, streams can be +mapped over with a function, merged with another stream of the same type or +filtered by some predicate.

+ +

Algebraic laws

+

Furthermore, streams satisfy certain algebraic properties that are useful to +reason about them.

+ +

Monoid

+

For once, streams of the same type form a monoid under merging. The +neutral element in this context is Stream::never(). So the following laws +always hold for streams a, b and c of the same type:

+ + + +

Note that equality in this context is not actually implemented as such, +since comparing two (potentially infinite) streams is a prohibitive +operation. Instead, the expressions above can be used interchangably and +behave identically.

+ +

Functor

+

Under the mapping operation streams also become a functor. A functor is a +generic type like Stream with some mapping operation that takes a function +Fn(A) -> B to map a Stream<A> to a Stream<B>. Algebraically it +satisfies the following laws:

+ + +

Methods

impl<A: Clone + Send + Sync + 'static> Stream<A>

fn never() -> Stream<A>

+

Create a stream that never fires. This can be useful in certain +situations, where a stream is logically required, but no events are +expected.

+

fn map<B, F>(&self, f: F) -> Stream<B> where B: Send + Sync + Clone + 'static, F: Fn(A) -> B + Send + Sync + 'static

+

Map the stream to another stream using a function.

+ +

map applies a function to every event fired in this stream to create a +new stream of type B.

+
+let sink: Sink<i32> = Sink::new();
+let mut events = sink.stream().map(|x| x + 4).events();
+sink.send(3);
+assert_eq!(events.next(), Some(7));
+
+

fn filter<F>(&self, f: F) -> Stream<A> where F: Fn(&A) -> bool + Send + Sync + 'static

+

Filter a stream according to a predicate.

+ +

filter creates a new stream that only fires those events from the +original stream that satisfy the predicate.

+
+let sink: Sink<i32> = Sink::new();
+let mut events = sink.stream()
+    .filter(|&x| (x >= 4) && (x <= 10))
+    .events();
+sink.send(2); // won't arrive
+sink.send(5); // will arrive
+assert_eq!(events.next(), Some(5));
+
+

fn filter_map<B, F>(&self, f: F) -> Stream<B> where B: Send + Sync + Clone + 'static, F: Fn(A) -> Option<B> + Send + Sync + 'static

+

Both filter and map a stream.

+ +

This is equivalent to .map(f).filter_some().

+
+let sink = Sink::new();
+let mut events = sink.stream()
+    .filter_map(|i| if i > 3 { Some(i + 2) } else { None })
+    .events();
+sink.send(2);
+sink.send(4);
+assert_eq!(events.next(), Some(6));
+
+

fn merge(&self, other: &Stream<A>) -> Stream<A>

+

Merge with another stream.

+ +

merge takes two streams and creates a new stream that fires events +from both input streams.

+
+let sink_1 = Sink::<i32>::new();
+let sink_2 = Sink::<i32>::new();
+let mut events = sink_1.stream().merge(&sink_2.stream()).events();
+sink_1.send(2);
+assert_eq!(events.next(), Some(2));
+sink_2.send(4);
+assert_eq!(events.next(), Some(4));
+
+

fn coalesce<F>(&self, f: F) -> Stream<A> where F: Fn(A, A) -> A + Send + Sync + 'static

+

Coalesce multiple event firings within the same transaction into a +single event.

+ +

The function should ideally commute, as the order of events within a +transaction is not well-defined.

+

fn hold(&self, initial: A) -> Signal<A>

+

Hold an event in a signal.

+ +

The resulting signal holds the value of the last event fired by the +stream.

+
+let sink = Sink::new();
+let signal = sink.stream().hold(0);
+assert_eq!(signal.sample(), 0);
+sink.send(2);
+assert_eq!(signal.sample(), 2);
+
+

fn events(&self) -> Events<A>

+

A blocking iterator over the stream.

+

fn scan<B, F>(&self, initial: B, f: F) -> Signal<B> where B: Send + Sync + Clone + 'static, F: Fn(B, A) -> B + Send + Sync + 'static

+

Scan a stream and accumulate its event firings in a signal.

+ +

Starting at some initial value, each new event changes the value of the +resulting signal as prescribed by the supplied function.

+
+let sink = Sink::new();
+let sum = sink.stream().scan(0, |a, b| a + b);
+assert_eq!(sum.sample(), 0);
+sink.send(2);
+assert_eq!(sum.sample(), 2);
+sink.send(4);
+assert_eq!(sum.sample(), 6);
+
+

fn scan_mut<B, F>(&self, initial: B, f: F) -> SignalMut<B> where B: Send + Sync + 'static, F: Fn(&mut B, A) + Send + Sync + 'static

+

Scan a stream and accumulate its event firings in some mutable state.

+ +

Semantically this is equivalent to scan. However, it allows one to use +a non-Clone type as an accumulator and update it with efficient in-place +operations.

+ +

The resulting SignalMut does have a slightly different API from a +regular Signal as it does not allow clones.

+ +

Example

+let sink: Sink<i32> = Sink::new();
+let sum = sink.stream()
+    .scan_mut(0, |sum, a| *sum += a)
+    .combine(&Signal::new(()), |sum, ()| *sum);
+assert_eq!(sum.sample(), 0);
+sink.send(2);
+assert_eq!(sum.sample(), 2);
+sink.send(4);
+assert_eq!(sum.sample(), 6);
+
+

impl<A: Clone + Send + Sync + 'static> Stream<Option<A>>

fn filter_some(&self) -> Stream<A>

+

Filter a stream of options.

+ +

filter_some creates a new stream that only fires the unwrapped +Some(…) events from the original stream omitting any None events.

+
+let sink = Sink::new();
+let mut events = sink.stream().filter_some().events();
+sink.send(None); // won't arrive
+sink.send(Some(5)); // will arrive
+assert_eq!(events.next(), Some(5));
+
+

impl<A: Send + Sync + Clone + 'static> Stream<Stream<A>>

fn switch(&self) -> Stream<A>

+

Switch between streams.

+ +

This takes a stream of streams and maps it to a new stream, which fires +all events from the most recent stream fired into it.

+ +

Example

+// Create sinks
+let stream_sink: Sink<Stream<i32>> = Sink::new();
+let sink1: Sink<i32> = Sink::new();
+let sink2: Sink<i32> = Sink::new();
+
+// Switch and listen
+let switched = stream_sink.stream().switch();
+let mut events = switched.events();
+
+// Should not receive events from either sink
+sink1.send(1); sink2.send(2);
+
+// Now switch to sink 2
+stream_sink.send(sink2.stream());
+sink1.send(3); sink2.send(4);
+assert_eq!(events.next(), Some(4));
+
+// And then to sink 1
+stream_sink.send(sink1.stream());
+sink1.send(5); sink2.send(6);
+assert_eq!(events.next(), Some(5));
+
+

Trait Implementations

impl<A> Clone for Stream<A>

fn clone(&self) -> Stream<A>

+

fn clone_from(&mut self, source: &Self)

+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/carboxyl/transaction/index.html b/carboxyl/transaction/index.html new file mode 100644 index 0000000..e69de29 diff --git a/carboxyl/transaction/sidebar-items.js b/carboxyl/transaction/sidebar-items.js new file mode 100644 index 0000000..48333d3 --- /dev/null +++ b/carboxyl/transaction/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({}); \ No newline at end of file -- cgit v1.2.3