给定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();
}
答案 0 :(得分:2)
直接传递f
并不起作用,因为Rc<T> where T: FnMut
没有实现FnMut
。
如果你的闭包没有执行任何变异(即它实现了Fn
),你可以改为编写&*f
。这是因为:
Rc
实现了Deref
,它改变了*
运算符的行为,使*x
扩展为*(x.deref())
,让我们可以访问包装的闭包。 *
运算符生成左值,允许您对结果进行引用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();
}
答案 1 :(得分:0)
啊! 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();
}
_ => ()
}
}
(虽然这可能是一种更清洁的方式)