rust - 在 Rust 中实现计算图

标签 rust

我正在尝试在 Rust 中实现类似 ReactiveX(例如,有点类似于 RxJava/RxJS 和 friend )的图形引擎,但仅面向同步计算,重点是中间值缓存。它有点像标准库迭代器,但倒退了。

我必须实现 Observable/Observer 模式的玩具原型(prototype):Playground -- 虽然它最终不是我想要的,但它展示了事物的一般精神。

基本上,我想要这样的代码(伪代码):

let mut input = Input();
let mut x = input.map(|i| i * 2);
// unavoidable multiple mut borrow?..
let mut y = x.fork().map(|x| x + 3) // [must_use]
y.subscribe(|y| println!("y={}", y)); // moved
let mut z = x.fork().map(|x| x - 4).do_more_stuff(); // [must_use]
z.subscribe(|z| println!("z={}", z)); // moved
// some time later:
input.feed(42);

大致展开成这样

|i| {
    let x = i * 2;
    let y = x + 3;
    println!("y={}", y);
    let z = do_more_stuff(x - 4);
    println!("z={}", z);
}

这里的语法很重要,我知道如何“倒退”或对其进行重大修改以使其有效,但为了可读性,我想尽可能保留“自上而下”的语法,'特别是 fork 。

所以你可以把它想象成一个有向图,在顶部有一个输入,每个节点进行一些计算并将结果(可能多次;或者可能不传递)传递到底层,可能是“forking”,这样就可以在不重新计算的情况下将值传递给多个下层节点。在最底层,有“订阅者/观察者”,他们可以倾听值(value)观并用它们做任何事情。一旦创建,这个图(即图结构)是完全不可变的。

在许多 Rx 框架的实现中,可以在不显式地将值作为结构字段携带的情况下执行此操作,因为它将存在于父闭包中。

我花了相当多的时间在 Rust 中思考和制作原型(prototype),但似乎无法找到一个很好的解决方案,既快速又“漂亮”,即符合人体工程学,如上面的示例所示。例如,使用 fork() (拆分流),所需的语法类型立即暗示对父级的多个可变借用,即使子级稍后被移动也是如此?

我认为可行的核心思想(在上面链接的 Playground 中实现)是:Observer 概念 - 基本上,一个特征需要实现者实现 on_next(&mut self, value: T) , 所以任何 FnMut(T) -> ()可以自动实现这个。然后,“ fork ”是包含 Box<Observer> 列表的东西。以便它可以调用它们。也许是一个“流/可观察”,它可以接受一个观察者订阅它(以可变的方式?)。

无论如何,也许我在这里撞到一堵众所周知的墙,或者也许有更好的解决方案(或者这可能已经在某处实现)——任何想法都将不胜感激。

最佳答案

这是可能的。基本上,this works :

let input = Input::<i64>::new();

let s1 = input.fork();
s1.subscribe(|x| {
    println!("s1: {}", x)
});

let s2 = input.fork();
s2.map(|x| x * 3).subscribe(|x| {
    println!("s2: {}", x)
});

let s3 = input.fork().map(|x| {
    let s3 = (x as f64) + 100.5;
    println!("s3: {}", s3);
    s3
}).share();

s3.fork().map(|x| x + 1.).subscribe(|x| println!("s4: {}", x));

s3.fork().map(|x| x + 2.).subscribe(|x| println!("s5: {}", x));

input.feed(1);
println!("---");
input.feed(2);

和输出

s1: 1
s2: 3
s3: 101.5
s4: 102.5
s5: 103.5
---
s1: 2
s2: 6
s3: 102.5
s4: 103.5
s5: 104.5

实现方面:Rc<RefCell<Vec<Box<Trait>>>>和很多生命周期标记...

关于rust - 在 Rust 中实现计算图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52959333/

相关文章:

mpi - Rust on 网格计算

rust - 迭代 Rust 中的命名正则表达式组

ld - 带有 Rust 的可移植二进制文件

rust - 使用格式化宏时如何编写文字引号?

rust - 如何从 Visual Studio Code 启动 Rust 应用程序?

rust - Rust 和旧迭代器模式中的生命周期

rust - 如何修复 `` Entirely Too Many Lists'' 第 2 章中损坏的 use 语句?

rust - 将代码生成标志添加到 Cargo 构建中

rust - 如何为 Clap Args 使用内部库枚举

rust - 你应该如何在 Rust 中进行指针运算?