Show the crate…
1 unstable release
0.1.1 | Mar 16, 2021 |
---|
#22 in #fp
59KB
942 lines
xi
Xi is a functional reactive stream library for rust.
- Small (~20 operations)
- Synchronous
- No dependencies
- Is FRP (ha!)
Modelled on André Staltz' javascript library xstream which nicely distills the ideas of reactive extensions (Rx) down to the essential minimum.
This library is not FRP (Functional Reactive Programming) in the way it was defined by Conal Elliot, but as a paradigm that is both functional and reactive. Why I cannot say FRP but I just did.
Example
use xi::{Sink, Stream};
// A sink is an originator of events that form a stream.
let sink: Sink<u32> = Stream::sink();
// Map the even numbers to their square.
let stream: Stream<u32> = sink.stream()
.filter(|i| i % 2 == 0)
.map(|i| i * i);
// Print the result
stream.subscribe(|i| if let Some(i) = i {
println!("{}", i)
});
// Send numbers into the sink.
for i in 0..10 {
sink.update(i);
}
sink.end();
Idea
Functional Reactive Programming is a good foundation for functional programming (FP). The step-by-step approach of composing interlocked operations, is a relatively easy way to make an FP structure to a piece of software.
Synchronous
Libraries that deals with streams as values-over-time (or events) often conflate the idea of moving data from point A to B, with the operators that transform the data. The result is that the library must deal with queues of data, queue lengths and backpressure.
xi has no queues
Every Sink::update()
of data into the tree of operations executes synchronously. xi
has no operators that dispatches "later", i.e. no delay()
or other time shifting
operations.
That also means xi also has no internal threads, futures or otherwise.
Thread safe
Every part of the xi tree is thread safe. You can move a Sink
into another thread,
or subscribe and propagate on a UI main thread. The thread that calls Sink::update()
is
the thread executing the entire tree.
That safety comes at a cost, xi is not a zero cost abstraction library. Every part of the tree is protected by a mutex lock. This is fine for most applications since a lock without contention is not much overhead in the execution. But if you plan on having lots of threads simultaneously updating many values into the tree, you might experience a performance hit due to lock contention.
Be out of your way
xi tries to impose a minimum of cognitive load when using it.
- Every operator is an
FnMut(&T)
to make it the most usable possible. - Not require
Sync
and/orSend
on operator functions. - xi stream instances themselves are
Sync
andSend
. - Impose a minimum of constraints the event value
T
.