提问人:mcmayer 提问时间:10/28/2022 更新时间:10/28/2022 访问量:270
异步移动闭包与折叠
Async move closure vs. fold
问:
异步闭包在 Rust 中仍然不稳定,正如相关问题中指出的那样 |_| async move {}
和 async move |_|{}
,我不太明白的答案。
据我了解,以下不是异步闭包:
let mut sum: i32 = 0;
stream::iter(1..25)
.map(compute)
.buffered(12)
.for_each(|result| async move { sum+=result; })
.await;
println!("->{}", sum);
我对此感到困惑,最初: 用于 ,但它没有被移动,否则会产生编译器错误。但是,编译器会发出警告,指出“从不读取分配给的值”。但是,事实上,总和是复制的。sum
for_each
println!
sum
下面是完整的示例代码
use futures::{stream, StreamExt};
use rand::{thread_rng, Rng};
use std::time::Duration;
async fn compute(i: i32) -> i32 {
let mut rng = thread_rng();
let sleep_ms: u64 = rng.gen_range(0..1000);
tokio::time::sleep(Duration::from_millis(sleep_ms)).await;
println!("#{} done", i);
i * i
}
async fn sum_with_fold() {
let sum = stream::iter(1..25)
.map(compute)
.buffered(12)
.fold(0, |sum,x| async move {sum+x} )
.await;
println!("->{}", sum);
}
async fn sum_with_closure() {
let mut sum: i32 = 0;
stream::iter(1..25)
.map(compute)
.buffered(12)
.for_each(|result| async move { sum+=result; })
.await;
println!("->{}", sum);
}
#[tokio::main]
async fn main() {
sum_with_fold().await;
sum_with_closure().await;
}
// Cargo.toml:
// [dependencies]
// futures = "0.3"
// rand = "0.8"
// tokio = { version = "1", features = ["full"] }
折叠可以正常工作,而折叠可以正常工作,而复制的折叠可以正常工作,并且无法检索。sum_with_closure
sum
sum
我做对了吗,可以修复吗?也就是说,有没有办法用这样的闭合来折叠?还是我确实遇到了不稳定的异步闭包功能?
答:
1赞
Jmb
10/28/2022
#1
这可以通过 来完成,但当前的 Rust 无法在编译时检查生存期是否正确,因此您需要使用 a 来启用运行时检查(性能成本很小):for_each
RefCell
async fn sum_with_closure() {
use std::cell::RefCell;
let sum = RefCell::new (0);
let sumref = ∑
stream::iter(1..25)
.map(compute)
.buffered(12)
.for_each(|result| async move { *sumref.borrow_mut() +=result; })
.await;
println!("->{}", sum.into_inner());
}
评论
0赞
Chayim Friedman
10/28/2022
StreamExt::for_each()
接受 ,因此不能同时调用它们。这只是当前的 Rust 无法(据我所知)表达这种模式。FnMut
0赞
Jmb
10/28/2022
@ChayimFriedman 好点,这不需要 ,只需要 .Mutex
RefCell
评论