给定一个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();
}给出误差
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();
}发布于 2018-01-21 03:11:26
直接传递f不起作用,因为Rc<T> where T: FnMut没有实现FnMut。
如果闭包没有执行任何变异(即它实现了Fn),则可以编写&*f。这样做是因为:
Rc实现Deref,这将改变*运算符的行为,从而使*x扩展到*(x.deref()),从而使我们能够访问包装好的闭包。*运算符生成一个lvalue,它允许您引用结果Fn 实施 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();
}矫顽力也适用于方法调用。虽然看起来不像,但f(v)实际上扩展到f.call((v,)) (从Rust 1.23开始)(注意这个语法是不稳定的,因此如果启用了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();
}发布于 2018-01-21 03:07:56
啊!try_unwrap将允许您移动对闭包的访问,而*f将提供对闭包的引用。
因此,解决办法可以是:
use std::rc::Rc;
fn main() {
let f = Rc::new(|x| x);
let v = vec![1, 2, 3];
match Rc::try_unwrap(f) {
Ok(f2) => {
let _: Vec<_> = v.into_iter().map(f2).collect();
}
_ => ()
}
}(虽然可能有一种更干净的方法来做这件事)
https://stackoverflow.com/questions/48363238
复制相似问题