我正在尝试在 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/