如何定义一个通用函数,该函数采用将切片转换为迭代器的函数
How to define a generic function that takes a function that converts a slice to an iterator
我想编写一个函数以不同的顺序处理一些切片,所以我决定编写一个在迭代顺序上通用的函数,例如:
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, 2, 3, 4];
make_iter(&mut data);
}
应该使用 ,但在该位置不允许使用 impl Iterator
。那有什么我可以做的吗?
更新:
要处理的切片应该被认为是在 foo
函数内部动态生成的,并在处理后被丢弃。
你的函数大部分是正确的。编译错误“借用的值寿命不够长”是由于您在 foo
中定义数据而不是将其传入。错误是因为行 let mut data = [1, 2, 3, 4];
data
的生命周期与函数 foo
相同,因为它是在函数 foo
中创建的。但是,闭包的生命周期比变量 data
长,因为闭包作为参数传入 foo
,因此它的生命周期比 data
长。当函数 foo
超出范围时, data
被删除。那么你的闭包正在尝试 return 一个已经被删除的引用 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, 2, 3, 4];
make_iter(data);
}
fn main() {
let mut data= vec![1,2,3,4];
foo(|x| x.iter_mut(), &mut data);
foo(|x| x.iter_mut().rev(), &mut data);
}
rustplay ground link : 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, 2, 3, 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, 2, 3, 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, slice: &'a mut [i32]) -> Self::Iter;
}
fn foo(mut make_iter: impl for<'a> MakeIter<'a>) {
let mut data = [1, 2, 3, 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);
}
我想编写一个函数以不同的顺序处理一些切片,所以我决定编写一个在迭代顺序上通用的函数,例如:
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, 2, 3, 4];
make_iter(&mut data);
}
应该使用 ,但在该位置不允许使用 impl Iterator
。那有什么我可以做的吗?
更新:
要处理的切片应该被认为是在 foo
函数内部动态生成的,并在处理后被丢弃。
你的函数大部分是正确的。编译错误“借用的值寿命不够长”是由于您在 foo
中定义数据而不是将其传入。错误是因为行 let mut data = [1, 2, 3, 4];
data
的生命周期与函数 foo
相同,因为它是在函数 foo
中创建的。但是,闭包的生命周期比变量 data
长,因为闭包作为参数传入 foo
,因此它的生命周期比 data
长。当函数 foo
超出范围时, data
被删除。那么你的闭包正在尝试 return 一个已经被删除的引用 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, 2, 3, 4];
make_iter(data);
}
fn main() {
let mut data= vec![1,2,3,4];
foo(|x| x.iter_mut(), &mut data);
foo(|x| x.iter_mut().rev(), &mut data);
}
rustplay ground link : 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, 2, 3, 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, 2, 3, 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, slice: &'a mut [i32]) -> Self::Iter;
}
fn foo(mut make_iter: impl for<'a> MakeIter<'a>) {
let mut data = [1, 2, 3, 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);
}