[英]Rust: error[E0495]: cannot infer an appropriate lifetime for autorefdue to conflicting requirements in closure
In a dummy project I have, I would like to use cycling iterators (to generate integers for example).在我的一个虚拟项目中,我想使用循环迭代器(例如生成整数)。
use std::iter::Cycle;
type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;
fn generate_cycles() -> [IntegerCycle; 2] {
let mut cycles = [
[1, 2].iter().cycle(),
[2, 4].iter().cycle(),
];
cycles
}
fn main() {
let mut cycles = generate_cycles();
// ...
}
Although the previous piece of code works as intended, my real world example is a bit more complicated, so I am looking to adapt the generate_cycles
function to be able to perform more operations (in the following example, multiply by 2, then generate the cycling iterators).尽管前一段代码按预期工作,但我的实际示例有点复杂,因此我希望调整
generate_cycles
函数以能够执行更多操作(在以下示例中,乘以 2,然后生成循环迭代器)。 For this, I tried to use arraymap :为此,我尝试使用arraymap :
extern crate arraymap;
use arraymap::ArrayMap;
use std::iter::Cycle;
type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;
fn generate_cycles() -> [IntegerCycle; 2] {
let mut cycles = [
[1, 2],
[2, 4],
];
cycles
.map(|points| {
points.map(|point| point*2)
})
.map(|points| {
points.iter().cycle()
})
}
fn main() {
let mut cycles = generate_cycles();
// ...
}
The above solution does not work, and, as a Rust beginner recently exposed to the concept of "lifetime", I do not understand why the compiler is complaining here, or what I can do to make him happy.上面的解决方案是行不通的,而且,作为一个最近接触到“生命周期”概念的 Rust 初学者,我不明白编译器为什么在这里抱怨,或者我可以做些什么让他开心。
error[E0495]: cannot infer an appropriate lifetime for autorefdue to conflicting requirements
--> src/main.rs:20:14
|
20 | points.iter().cycle()
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 19:10...
--> src/main.rs:19:10
|
19 | .map(|points| {
| __________^
20 | | points.iter().cycle()
21 | | })
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:20:7
|
20 | points.iter().cycle()
| ^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected [std::iter::Cycle<std::slice::Iter<'static, i32>>; 2]
found [std::iter::Cycle<std::slice::Iter<'_, i32>>; 2]
Here is a REPL with the code trying to make use of the arraymap
: https://repl.it/repls/ShadowyStrikingFirm .这是一个尝试使用
arraymap
的代码的 REPL: https : arraymap
。
In your type declaration:在您的类型声明中:
type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;
You say that you the underlying slices you use to build your iterators must have 'static
lifetime, that is, they must live forever.您说用于构建迭代器的底层切片必须具有
'static
生命周期”,即它们必须永远存在。 Then you use literal arrays such as [1, 2]
that, as all literals, have 'static'
lifetime and all goes well:然后您使用文字数组,例如
[1, 2]
,与所有文字一样,具有'static'
生命周期并且一切顺利:
let r: &'static [i32; 2] = &[1, 2]; //Ok
But then, you try a code similar to this simpler one:但是,您尝试使用类似于这个更简单的代码的代码:
let a = [1, 2].map(|x| 2 * x);
let r: &'static [i32; 2] = &a; //error: borrowed value does not live long enough
That is the result of arraymap::map
is a normal array, not a literal one, so it does not have a 'static
lifetime.那是
arraymap::map
的结果是一个普通数组,而不是文字数组,因此它没有'static
生命周期”。 It cannot be static because you are computing the values in runtime.它不能是静态的,因为您是在运行时计算值。 It will live as long as necessary, in my case as long as the variable
a
.只要有必要,它就会一直存在,在我的情况下,只要变量
a
。
In your case, since the returns of arraymap::map
are not assigned to variables, they are temporary values and they are quickly dropped.在您的情况下,由于
arraymap::map
的返回值未分配给变量,因此它们是临时值并且会很快被删除。 But even if you assigned it to a local variable, you could not return a reference to it, because the local variable is dropped when the function ends.但是即使你将它分配给一个局部变量,你也不能返回对它的引用,因为当函数结束时局部变量被删除了。
The solution is to return an iterator that owns the value.解决方案是返回一个拥有该值的迭代器。 Something like this works:
像这样的工作:
type IntegerCycle = Cycle<std::vec::IntoIter<i32>>;
fn generate_cycles() -> [IntegerCycle; 2] {
let cycles = [
[1, 2],
[2, 4],
];
cycles
.map(|points| {
points.map(|point| point*2)
})
.map(|points| {
points.to_vec().into_iter().cycle()
})
}
Unfortunately you have to use a Vec
instead of an array, because there is not an IntoIterator
implementation for arrays, (there are for slices, but they do not own the values).不幸的是,您必须使用
Vec
而不是数组,因为数组没有IntoIterator
实现(有切片,但它们不拥有值)。
If you want to avoid the extra allocation of Vec
you can use the arrayvec
crate that does allow to take an iterator to an array:如果你想避免
Vec
的额外分配,你可以使用允许将迭代器带到数组的arrayvec
板条箱:
type IntegerCycle = Cycle<arrayvec::IntoIter<[i32; 2]>>;
fn generate_cycles() -> [IntegerCycle; 2] {
let cycles = [
[1, 2],
[2, 4],
];
cycles
.map(|points| {
points.map(|point| point*2)
})
.map(|points| {
let a = arrayvec::ArrayVec::from(*points);
a.into_iter().cycle()
})
}
NOTE: It looks like there is an attempt to add a proper IntoIterator
impl for arrays by value to the std
, but there are still some pending issues.注意:似乎有尝试为数组按值添加适当的
IntoIterator
impl到std
,但仍然存在一些未决问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.