2个版本

0.1.1 2019年2月17日
0.1.0 2019年2月16日

#939 in 数据结构

MIT 协议

59KB
942

福罗普

一个为Rust设计的函数式响应式流库。

  • 小型 (~20 个操作)
  • 同步
  • 无依赖
  • 是 FRP (哈哈!)

基于André Staltz的JavaScript库 xstream 设计,该库很好地将响应式扩展 (Rx) 的概念简化到最基本的形式。

这个库并不是按照Conal Elliot的定义那样是 FRP (函数式响应式编程),而是一种既函数式又响应式的设计范式。 为什么我不能说FRP但我确实做到了

示例

use froop::{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();

想法

函数式响应式编程是函数式编程 (FP) 的良好基础。逐步组合互锁操作的步骤是一种相对简单的方法,可以将FP结构应用于软件。

同步

处理作为时间值(或事件)的流的库通常将数据从A点移动到B点的概念与转换数据的算子混淆。结果是,库必须处理数据队列、队列长度和背压。

福罗普没有队列

将数据更新到操作树的每个 Sink::update() 都以同步方式执行。福罗普没有调度“稍后”的算子,即没有 delay() 或其他时间移位操作。

这也意味着福罗普也没有内部线程、future等。

线程安全

福罗普树中的每个部分都是线程安全的。您可以将在另一个线程中移动 Sink,或订阅和传播在UI主线程上。调用 Sink::update() 的线程执行整个树。

安全是有代价的,froop不是一个零成本抽象库。树中的每一部分都受到互斥锁的保护。这对于大多数应用程序来说是可以的,因为无争用的锁在执行中不会造成太多开销。但是,如果您计划同时使用大量线程更新树中的许多值,您可能会因为锁争用而体验到性能下降。

不要碍事

Froop在使用时尽量减少认知负担。

  • 每个操作符都是一个FnMut(&T),使其尽可能易用。
  • 操作符函数不需要Sync和/或Send
  • Froop流实例本身是SyncSend
  • 对事件值T施加最小的约束。

无运行时依赖