#frp #threading #gui

cfrp

Concurrent Functional Reactive Programming for Rust

4 releases

Uses old Rust 2015

0.0.4 Aug 22, 2015
0.0.3 May 20, 2015
0.0.2 May 18, 2015
0.0.1 Apr 25, 2015

#21 in #frp

MIT license

65KB
1.5K SLoC

Concurrent Functional Reactive Programming (for Rust)

Concurrent FRP implemented in Rust.

Build Status

Documentation

This is essentially a port of Elm. If you're not familiar with Elm or the design behind Evan Czaplicki's Concurrent FRP, you should read Elm: Concurrent FRP for Functional GUIs or watch his talk at StrangeLoop 2014.

Other Options (that I know of):

TODO

  • docs / logs
  • implement Display/Debug
  • Try to eliminate constraints

lib.rs:

Concurrent Function Reactive Programming

Highly influenced by Elm - provides a framework for describing & executing concurrent data flow processes.

Examples

use std::default::*;
use std::sync::mpsc::*;
use cfrp::*;

// create some channels for communicating with the topology
let (in_tx, in_rx) = channel();

// Topologies are statically defined, run-once structures.  Due to how
// concurrency is handled, changes to the graph structure can cause
// inconsistencies in the data processing
// 
spawn_topology(Default::default(), |t| {

    // Create a listener on `in_rx` with initial value `0`.  Messages 
    // received on the channel will be sent to any nodes subscribed to `input`
    let input = t.listen(0usize, in_rx).add_to(t);

    // Basic map operation.  Since this is expected to be a pure function, 
    // it will only be evaluated when the value of `input` changes
    let plus_one = input.lift(|i| { i + 1 }).add_to(t);

    // The return value of `add` / `add_to` implements `clone`, and can be used to
    // 'fan-out' data
    let plus_two = plus_one.clone().lift(|i| { i + 2 });

    // We can combine signals too.  Since it's possible to receive input on one
    // side but not the other, `lift2` wraps data in a `Value<T>` which is 
    // either `Value::Changed(T)` or `Value::Unchanged(T)`.  Like `lift`, 
    // this function is only called when needed
    let combined = plus_one.lift2(plus_two, |i, j| { *i + *j });

    // `fold` allows us to track state across events.  
    let accumulated = combined.fold(0, |sum, i| { sum + i });

    // Make sure to add transformations to the topology with `add` / `add_to`
    // I it's not added it won't be run...
    t.add(accumulated);
});

in_tx.send(1usize).unwrap();

Dependencies

~1.5MB
~23K SLoC