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