如何解决如何定义一个通用函数,该函数采用将切片转换为迭代器的函数
我想编写一个函数,以不同的顺序处理一些切片,所以我决定编写一个在迭代顺序上通用的函数,例如:
fn foo<'a,I: Iterator<Item = &'a mut i32>>(make_iter: impl Fn(&'a mut [i32]) -> I) {
let mut data = [1,2,3,4];
make_iter(&mut data);
}
fn main() {
foo(|x| x.iter_mut());
foo(|x| x.iter_mut().rev());
}
这会导致“借来的价值寿命不够长”错误。
我想像这样
fn foo(make_iter: impl for<'a> Fn(&'a mut [i32]) -> impl Iterator<Item = &'a mut i32>) {
let mut data = [1,4];
make_iter(&mut data);
}
应该被使用,但 impl Iterator
在那个位置是不允许的。那么我有什么可以做的吗?
更新:
要处理的切片应被视为在 foo
函数内部动态生成,并在处理后删除。
解决方法
你的函数大部分是正确的。编译错误“借用的值寿命不够长”是由于您在 foo
中定义数据而不是将其传入。错误是由于行let mut data = [1,2,3,4];
>
data
的生命周期与函数 foo
相同,因为它是在函数 foo
中创建的。然而,闭包的生命周期比变量 data
长,因为闭包作为参数传入 foo
,因此它的生命周期比 data
长。当函数 foo
超出范围时,data
被删除。然后你的闭包试图返回一个已经被删除的引用 data
。这就是为什么你编译错误“借来的价值活得不够长”。
您可以通过将数据作为参数传递到 foo
来进行编译,在这种情况下,您不会因生命周期而出现问题。
下面的代码将被编译。
fn foo<'a,I: Iterator<Item = &'a mut i32>>(make_iter: impl Fn(&'a mut [i32]) -> I,data: &'a mut Vec<i32>) {
// let mut data = [1,4];
make_iter(data);
}
fn main() {
let mut data= vec![1,4];
foo(|x| x.iter_mut(),&mut data);
foo(|x| x.iter_mut().rev(),&mut data);
}
rustplay 地面链接:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8b263451fcb01518b3f35bda8485af9c
更新:请尽量误解您的要求。我试图找到一种干净的方式来写这个,但我能想到的最好的方法是使用 Box<dyn
来做。我知道 Box<dyn...
有运行时成本,但我想不出更好的方法来使用 impl Iterator
使用 Box<dyn ...
的实现是
fn foo<F>(make_iter: F) where for<'a> F: Fn(&'a mut [i32])->Box<dyn Iterator<Item=&'a mut i32>+'a>{
let mut data = vec![1,4];
make_iter(&mut data);
}
fn main() {
foo(|x| Box::new(x.iter_mut()));
foo(|x| Box::new(x.iter_mut().rev()));
}
,
我想出了一个解决方案:
use std::iter::Rev;
use std::slice::IterMut;
trait MakeIter<'a> {
type Iter: Iterator<Item = &'a mut i32>;
fn make_iter(&mut self,slice: &'a mut [i32]) -> Self::Iter;
}
fn foo(mut make_iter: impl for<'a> MakeIter<'a>) {
let mut data = [1,4];
make_iter.make_iter(&mut data);
}
struct Forward;
impl<'a> MakeIter<'a> for Forward {
type Iter = IterMut<'a,i32>;
fn make_iter(&mut self,slice: &'a mut [i32]) -> Self::Iter {
slice.iter_mut()
}
}
struct Backward;
impl<'a> MakeIter<'a> for Backward {
type Iter = Rev<IterMut<'a,i32>>;
fn make_iter(&mut self,slice: &'a mut [i32]) -> Self::Iter {
slice.iter_mut().rev()
}
}
fn main() {
foo(Forward);
foo(Backward);
}
但我不确定是否可以简化。
更新
这里是一个简化:
trait MakeIter<'a> {
type Iter: Iterator<Item = &'a mut i32>;
fn make_iter(&mut self,4];
make_iter.make_iter(&mut data);
}
impl<'a,F,R> MakeIter<'a> for F
where
F: FnMut(&'a mut [i32]) -> R,R: Iterator<Item = &'a mut i32>,{
type Iter = R;
fn make_iter(&mut self,slice: &'a mut [i32]) -> Self::Iter {
self(slice)
}
}
fn iter_forward(slice: &mut [i32]) -> impl Iterator<Item = &mut i32> {
slice.iter_mut()
}
fn iter_backward(slice: &mut [i32]) -> impl Iterator<Item = &mut i32> {
slice.iter_mut().rev()
}
fn main() {
foo(iter_forward);
foo(iter_backward);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。