gpt4 book ai didi

rust - 使用 Rc 作为 FnMut

转载 作者:行者123 更新时间:2023-11-29 08:14:11 24 4
gpt4 key购买 nike

给定一个 Rc<FnMut> ,在迭代器上映射时如何使用它?例如:

use std::rc::Rc;

fn main() {
let f = Rc::new(|x| x);
let v = vec![1, 2, 3];
let _: Vec<_> = v.into_iter().map(f).collect();
}

playground

给出错误

error[E0277]: the trait bound `std::rc::Rc<[closure@src/main.rs:6:21: 6:26]>: std::ops::FnMut<({integer},)>` is not satisfied
--> src/main.rs:8:35
|
8 | let _: Vec<_> = v.into_iter().map(f).collect();
| ^^^ the trait `std::ops::FnMut<({integer},)>` is not implemented for `std::rc::Rc<[closure@src/main.rs:6:21: 6:26]>`

error[E0599]: no method named `collect` found for type `std::iter::Map<std::vec::IntoIter<{integer}>, std::rc::Rc<[closure@src/main.rs:6:21: 6:26]>>` in the current scope
--> src/main.rs:8:42
|
8 | let _: Vec<_> = v.into_iter().map(f).collect();
| ^^^^^^^
|
= note: the method `collect` exists but the following trait bounds were not satisfied:
`std::iter::Map<std::vec::IntoIter<{integer}>, std::rc::Rc<[closure@src/main.rs:6:21: 6:26]>> : std::iter::Iterator`
`&mut std::iter::Map<std::vec::IntoIter<{integer}>, std::rc::Rc<[closure@src/main.rs:6:21: 6:26]>> : std::iter::Iterator`

我想一个简单的*f会解决问题,但后来我得到一个 cannot move out of borrowed content错误。

我最接近的是这个:

use std::rc::Rc;

fn main() {
let mut f = Rc::new(|x| x);
let v = vec![1, 2, 3];
let _: Vec<_> = v.into_iter().map(Rc::get_mut(&mut f).unwrap()).collect();
}

playground

最佳答案

传递 f直接不行,因为Rc<T> where T: FnMut没有实现 FnMut .

如果你的闭包没有执行任何改变(即它实现了 Fn ),你可以写成 &*f反而。这是有效的,因为:

  1. Rc工具 Deref ,它改变了 * 的行为运算符 *x扩展为 *(x.deref()) ,让我们可以访问包裹的闭包。
  2. *运算符产生一个左值,它允许您引用结果
  3. 对实现 Fn 的类型的不可变引用implement FnMut .
use std::rc::Rc;

fn main() {
let f = Rc::new(|x| x);
let v = vec![1, 2, 3];
let _: Vec<_> = v.into_iter().map(&*f).collect();
}

然而,&mut *f如果闭包存储在 Rc 中将不起作用,因为 Rc没有实现 DerefMut ,因此不允许我们可变地借用它的内部。

另一种选择是传递一个调用 f 的闭包至 map .

use std::rc::Rc;

fn main() {
let f = Rc::new(|x| x);
let v = vec![1, 2, 3];
let _: Vec<_> = v.into_iter().map(|v| f(v)).collect();
}

Deref coercions are also applied on method calls.虽然它看起来不像一个,f(v)实际上扩展(从 Rust 1.23 开始)到 f.call((v,)) (请注意,此语法不稳定,因此如果启用了 fn_traits 功能,则只有夜间编译器会接受它)。


如果闭包在 Box 中相反,你可以写 &mut *f ,因为 Box工具 DerefMut .

fn main() {
let mut f = Box::new(|x| x);
let v = vec![1, 2, 3];
let _: Vec<_> = v.into_iter().map(&mut *f).collect();
}

关于rust - 使用 Rc<FnMut> 作为 FnMut,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48363238/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com