1 个不稳定版本

使用旧的 Rust 2015

0.1.1 2018年11月12日

#21#functional-reactive-programming

28 每月下载量
用于 stocker

MIT 许可证

40KB
478

reactive-rs

Build Docs

此包为 Rust 中的函数式响应式编程(FRP)提供构建块。它受到了 carboxylfrappebidule 包以及各种 ReactiveX 实现的启发。

文档

docs.rs/reactive-rs

目的

该库的主要用途是简化创建高效的计算 DAG(或计算树)的过程,这些 DAG 或计算树在值流上操作。它不旨在复制整个 ReactiveX 操作符系列,也不旨在深入探讨 futures/concurrency 领域。

什么是计算树?首先,在顶部有一个根节点,输入值持续地被输入到这里。然后,我们对这些值进行计算——每个计算可能产生零个、一个或多个要进一步发送的值。一些下游节点可能共享其父节点——例如,g(f(x))h(f(x)),其中 x 是输入值,f 是中间转换;在这种情况下,我们希望确保不需要两次重新计算 f(x)。此外,由于是 Rust,我们希望确保不无谓地复制和克隆任何值,并且在可能的情况下,我们更喜欢将事物设置为无成本/内联。最后,有叶子节点——这些是观察者,它们接收转换值并对其执行某些操作,很可能是在某个地方记录它们或在某种方式中修改环境。

上下文

该包中的流、广播和观察者操作于值的成对:上下文和元素。上下文可以被视为附加到原始值上的可选元数据。在 .map() 等方法中所需的功能闭包只接受一个参数(元素)并期望返回单个值;这样,元素可以更改而不触及上下文。如果需要在计算链的深处访问原始输入值(或任何“上游”值),这会非常方便——这样就不需要显式传播它。

大多数流/广播方法都有一个操作于上下文/元素的替代“完整”版本,带有 _ctx 后缀。

使用示例

考虑以下问题:我们有一个买入/卖出价格对的输入流,并且对于每个输入事件,我们希望计算当前中间价(两个价格的平均值)与过去三个观测中的最低买入价和最高卖出价相比的相对值。此外,我们希望跳过前几个事件,以便缓冲区充满。

以下是一种我们可以实现的方法(这并不是解决这个特定问题的最最终有效方法,但它很好地演示了crate的基本功能)

use std::cell::Cell;
use std::f64;
use reactive_rs::*;

let min_rel = Cell::new(0.);
let max_rel = Cell::new(0.);

// create a broadcast of (buy, sell) pairs
let quotes = SimpleBroadcast::new();

// clone the broadcast so we can feed values to it later
let last = quotes.clone()
    // save the mid-price for later use
    .with_ctx_map(|_, &(buy, sell)| (buy + sell) / 2.)
    // cache the last three observations
    .last_n(3)
    // wait until the queue fills up
    .filter(|quotes| quotes.len() > 2)
    // share the output (slices of values)
    .broadcast();

// subscribe to the stream of slices
let min = last.clone()
    // compute min buy price
    .map(|p| p.iter().map(|q| q.0).fold(1./0., f64::min));
// subscribe to the stream of slices
let max = last.clone()
    // compute max sell price
    .map(|p| p.iter().map(|q| q.1).fold(-1./0., f64::max));

// finally, attach observers
min.subscribe_ctx(|p, min| min_rel.set(min / p));
max.subscribe_ctx(|p, max| max_rel.set(max / p));

quotes.send((100., 102.));
quotes.send((101., 103.));
assert_eq!((min_rel.get(), max_rel.get()), (0., 0.));
quotes.send((99., 101.));
assert_eq!((min_rel.get(), max_rel.get()), (0.99, 1.03));
quotes.send((97., 103.));
assert_eq!((min_rel.get(), max_rel.get()), (0.97, 1.03));

许可证

MIT许可证(MIT)

版权所有(c)2018 伊万·斯米诺夫

特此授予任何获得此软件及其相关文档副本(“软件”)的个人免费使用软件的权利,不受任何限制,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许获得软件的个人这样做,但需遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或实质性部分中。

软件按“原样”提供,不提供任何形式的保证,无论是明示的、暗示的,包括但不限于适销性、特定用途适用性和非侵权性保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任承担责任,无论源于合同、侵权或其他原因,与软件有关,或与使用或操作软件有关。

依赖项

约240-460KB