Rust “生锈错误”;无法推断借用表达式“的适当生存期”;当试图在返回迭代器的闭包内改变状态时

Rust “生锈错误”;无法推断借用表达式“的适当生存期”;当试图在返回迭代器的闭包内改变状态时,rust,lifetime,Rust,Lifetime,我试图学习Rust,在尝试模拟嵌套Python生成器时遇到了与生命周期相关的问题。问题在于编译器报告的由闭包突变的值的生存期。代码的关键是平面映射一个闭包,该闭包调用一个函数,该函数在返回的迭代器中对外部作用域提供的值进行变异。请参见中的第39行 这里的代码是原始程序的简化版本。因为我的最终目标是了解更多关于生锈的知识,所以我更希望了解一些细节,而不是修复我的代码 例如,一个“解决方案”是第44行注释掉的代码。它“起作用”,但总是分配一个包含跟踪上所有点的Vec,即使用户只想检查跟踪上的第一个点

我试图学习Rust,在尝试模拟嵌套Python生成器时遇到了与生命周期相关的问题。问题在于编译器报告的由闭包突变的值的生存期。代码的关键是平面映射一个闭包,该闭包调用一个函数,该函数在返回的迭代器中对外部作用域提供的值进行变异。请参见中的第39行

这里的代码是原始程序的简化版本。因为我的最终目标是了解更多关于生锈的知识,所以我更希望了解一些细节,而不是修复我的代码

例如,一个“解决方案”是第44行注释掉的代码。它“起作用”,但总是分配一个包含跟踪上所有点的
Vec
,即使用户只想检查跟踪上的第一个点,它也会忽略该点

我认为问题与可变借阅点
如何存在于
trace\u steps
返回的迭代器中有关。我尝试了太多的变体,从传入从
main
(更类似于
trace\u step
的工作方式)变异而来的
,到在我开始绝望时试图盲目使用
Rc

以下是从is复制的代码:

#[派生(调试、均衡、部分q)]
结构点{
x:i32,
y:i32,
}
内点{
fn新(x:i32,y:i32)->点{
点{x,y}
}
}
//其目的是,这就像一个Python生成器。通常情况下,“步骤”是
//可以是具有方向和长度的结构,但这是一个简化版本。
fn trace_step impl迭代器+'a{
让mut len=阶跃;
标准:国际热核聚变实验堆:从| fn(移动| |{
如果len==0{
没有一个
}否则{
len-=1;
点x+=1;
一些(点{..*点})
}
})
}
//修复:请参阅编译器错误!!!
//编译器无法推断借用点和mut点的适当生存期。

//借钱人就不能活得和关门一样长吗? // //其目的是沿着由多个路径定义的路径生成点 //步骤。简化。 fn trace_steps(steps:Vec)->impl迭代器{ 让mut point:point=point::new(0,0); //这不管用。 设f=| x:&u8 |跟踪|步进(&mut point,*x); steps.iter().平面图(f) //这是可行的,但我们不想承诺为所有人分配空间 //如果用户只需要计算点数,则为点数。 /* 让mut-ret:Vec=Vec::new(); 一步一步地{ ret.extend(跟踪步骤(&mut点,步骤)); } 改为 */ } fn main(){ 让mut point:point=point::new(0,0); let points:Vec=trace_step(&mut point,3).collect(); //输出:[点{x:1,y:0},点{x:2,y:0},点{x:3,y:0}] println!(“{:?}”,点); //应该从(0,0)跟踪第一步到(1,0),然后跟踪第二步 //从(1,0)到(2,0)到(3,0)。 let points:Vec=trace_steps(Vec![1,2])。collect(); println!(“{:?}”,点); }
在中运行时的错误是:

编译操场v0.0.1(/playerd)
错误[E0495]:由于需求冲突,无法推断借用表达式的适当生存期
-->src/main.rs:38:33
|
38 |设f=|x:&u8 |跟踪|步进(&mut point,*x);
|                                 ^^^^^^^^^^
|
注:首先,寿命不能超过38:13时身体上定义的寿命“uu”。。。
-->src/main.rs:38:13
|
38 |设f=|x:&u8 |跟踪|步进(&mut point,*x);
|             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
注意:…以便闭包可以访问`点`
-->src/main.rs:38:33
|
38 |设f=|x:&u8 |跟踪|步进(&mut point,*x);
|                                 ^^^^^^^^^^
注意:但是,生存期必须对34:63处表达式周围的销毁范围有效。。。
-->src/main.rs:34:63
|
34 | fn trace_步骤(步骤:Vec)->impl迭代器{
|  _______________________________________________________________^
35 | |让mut point:point=point::new(0,0);
36 | |     
37 | |//FIXME:这不管用。
...  |
49 | |     */
50 | | }
| |_^
注意:…以便在析构函数运行时引用有效
-->src/main.rs:34:63
|
34 | fn trace_步骤(步骤:Vec)->impl迭代器{
|  _______________________________________________________________^
35 | |让mut point:point=point::new(0,0);
36 | |     
37 | |//FIXME:这不管用。
...  |
49 | |     */
50 | | }
| |_^
错误:由于上一个错误而中止
错误:无法编译“游乐场”。

问题在于Rust对复制可变引用非常严格。这是一个问题,因为当您在
flat\u map
中返回迭代器时,迭代器必须具有对点的可变(唯一)引用,但是
flat\u map
不够健壮,无法将迭代器返回给您,因此,Rust不能证明在再次调用闭包时,最后一个迭代器仍然没有引用该点。一旦发电机稳定下来,这将是微不足道的正确操作。同时,这仍然是可能的,但是比我预期的困难得多,您需要手动实现
迭代器
特性。给你:

使用std::iter::{ExactSizeInterator,FuseEditor};
#[派生(克隆、复制、调试、Eq、PartialEq)]
结构点{
x:i32,
y:i32,
}
内点{
fn新(x:i32,y:i32)->点{
自{x,y}
}
}
#[导出(调试)]
结构步进跟踪器{
fn新(点:&'a多点,透镜:u8)->自身{
自{点,len}
}
fn进入_内部(自身)->&多点{
自我点
}
}
恳求{
类型项=点;
fn下一步(多个自身(&M)-
   Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
  --> src/main.rs:38:33
   |
38 |     let f = |x: &u8| trace_step(&mut point, *x);
   |                                 ^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 38:13...
  --> src/main.rs:38:13
   |
38 |     let f = |x: &u8| trace_step(&mut point, *x);
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `point`
  --> src/main.rs:38:33
   |
38 |     let f = |x: &u8| trace_step(&mut point, *x);
   |                                 ^^^^^^^^^^
note: but, the lifetime must be valid for the destruction scope surrounding expression at 34:63...
  --> src/main.rs:34:63
   |
34 |   fn trace_steps(steps: Vec<u8>) -> impl Iterator<Item = Point> {
   |  _______________________________________________________________^
35 | |     let mut point: Point = Point::new(0, 0);
36 | |     
37 | |     // FIXME: This doesn't work.
...  |
49 | |     */
50 | | }
   | |_^
note: ...so that references are valid when the destructor runs
  --> src/main.rs:34:63
   |
34 |   fn trace_steps(steps: Vec<u8>) -> impl Iterator<Item = Point> {
   |  _______________________________________________________________^
35 | |     let mut point: Point = Point::new(0, 0);
36 | |     
37 | |     // FIXME: This doesn't work.
...  |
49 | |     */
50 | | }
   | |_^

error: aborting due to previous error

error: could not compile `playground`.
Path for original example: [Point { x: 1, y: 0 }, Point { x: 2, y: 0 }, Point { x: 3, y: 0 }]
End point for bonus example: Point { x: 3, y: 0 }