[英]Rust: guidance on recursive function mutating vectors
I need some guidance how to approach a recursive function that needs to mutate the vectors that are provided to it from previous recursion level.我需要一些指导如何处理递归 function 需要改变从以前的递归级别提供给它的向量。
fn solve (graph: &CompleteGraph) -> Path {
let mut path = Path { cities: Vec::<usize>::new() };
let mut visited = Visited { cities: vec!(false; graph.numcities) };
let since = Instant::now();
let bestpath = Path { cities: trivialpath(&graph) };
let besttotal = pathtotal(&bestpath.cities, &graph);
let (path, visited, bestpath, besttotal) = solverec(path, 0.0, visited, since, bestpath, besttotal);
return bestpath;
}
fn solverec (path: Path, pathtotal: f64, visited: Visited, since: Instant, bestpath: Path, besttotal: f64) -> (Path, Visited, Path, f64) {
if since.elapsed() > Duration::from_secs(5) {
return (path, visited, bestpath, besttotal);
}
if pathtotal > besttotal {
return (path, visited, bestpath, besttotal);
}
for nextcity in 0..visited.cities.len() {
if visited.cities[nextcity] == false {
path.cities.push(nextcity);
visited.cities[nextcity] = true;
let (path, visited, bestpath, besttotal) = solverec(path, pathtotal, visited, since, bestpath, besttotal);
visited.cities[nextcity] = false;
path.cities.pop();
}
}
unimplemented!();
}
Compiler complains a lot:编译器抱怨很多:
error[E0382]: borrow of moved value: `visited`
--> tsp-arekbulski-05-brute.rs:123:6
|
113 | ...verec (path: Path, pathtotal: f64, visited: Visited, since: Instant, bestpath: Path, best...
| ------- move occurs because `visited` has type `Visited`, which does not implement the `Copy` trait
...
123 | ...isited.cities[nextcity] == false {
| ^^^^^^^^^^^^^^ value borrowed here after move
...
126 | ... (path, visited, bestpath, besttotal) = solverec(path, pathtotal, visited, since, bestpat...
| ------- value moved here, in previous iteration of loop
error[E0596]: cannot borrow `path.cities` as mutable, as `path` is not declared as mutable
--> tsp-arekbulski-05-brute.rs:124:4
|
113 | fn solverec (path: Path, pathtotal: f64, visited: Visited, since: Instant, bestpath: Path, b...
| ---- help: consider changing this to be mutable: `mut path`
...
124 | path.cities.push(nextcity);
| ^^^^^^^^^^^ cannot borrow as mutable
error[E0382]: borrow of moved value: `path`
--> tsp-arekbulski-05-brute.rs:124:4
|
113 | fn solverec (path: Path, pathtotal: f64, visited: Visited, since: Instant, bestpath: Path, b...
| ---- move occurs because `path` has type `Path`, which does not implement the `Copy` trait
...
124 | path.cities.push(nextcity);
| ^^^^^^^^^^^ value borrowed here after move
125 | visited.cities[nextcity] = true;
126 | let (path, visited, bestpath, besttotal) = solverec(path, pathtotal, visited, since, best...
| ---- value moved here, in previous iteration of loop
error[E0596]: cannot borrow `visited.cities` as mutable, as `visited` is not declared as mutable
--> tsp-arekbulski-05-brute.rs:125:4
|
113 | fn solverec (path: Path, pathtotal: f64, visited: Visited, since: Instant, bestpath: Path, b...
| ------- help: consider changing this to be mutable: `mut visited`
...
125 | visited.cities[nextcity] = true;
| ^^^^^^^^^^^^^^ cannot borrow as mutable
error[E0382]: use of moved value: `bestpath`
--> tsp-arekbulski-05-brute.rs:126:89
|
113 | ...sited, since: Instant, bestpath: Path, besttotal: f64) -> (Path, Visited, Path, f64) {
| -------- move occurs because `bestpath` has type `Path`, which does not implement the `Copy` trait
...
126 | ...ec(path, pathtotal, visited, since, bestpath, besttotal);
| ^^^^^^^^ value moved here, in previous iteration of loop
error[E0596]: cannot borrow `visited.cities` as mutable, as `visited` is not declared as mutable
--> tsp-arekbulski-05-brute.rs:127:4
|
126 | let (path, visited, bestpath, besttotal) = solverec(path, pathtotal, visited, since, best...
| ------- help: consider changing this to be mutable: `mut visited`
127 | visited.cities[nextcity] = false;
| ^^^^^^^^^^^^^^ cannot borrow as mutable
error[E0596]: cannot borrow `path.cities` as mutable, as `path` is not declared as mutable
--> tsp-arekbulski-05-brute.rs:128:4
|
126 | let (path, visited, bestpath, besttotal) = solverec(path, pathtotal, visited, since, best...
| ---- help: consider changing this to be mutable: `mut path`
127 | visited.cities[nextcity] = false;
128 | path.cities.pop();
| ^^^^^^^^^^^ cannot borrow as mutable
error: aborting due to 7 previous errors; 7 warnings emitted
let (path, visited, bestpath, besttotal) = solverec(path, pathtotal, visited, since, bestpath, besttotal);
This consumes the 4 function-local variables, and shadows them with 4 loop-local variables.这消耗了 4 个函数局部变量,并用 4 个循环局部变量隐藏它们。
So the loop can only execute once, afterwards there's nothing to use: loop-local variables are dropped at the end of the loop .所以循环只能执行一次,之后就没有什么可使用的了:循环局部变量在循环结束时被丢弃。
You may have tried to use this because a mass-reassignment您可能曾尝试使用它,因为大规模重新分配
(path, visited, bestpath, besttotal) = ...
did not work.不工作。
And sadly, no it does not, reassignments are not patterns so you can't use destructuring reassignments, and no a re-declaration does not fix it.可悲的是,不,它没有,重新分配不是模式,所以你不能使用解构重新分配,并且没有重新声明不能解决它。 You have to make the function-local bindings
mut
, then reassign explicitly from the loop-local results you got from solverec
eg您必须使函数局部绑定
mut
,然后从您从solverec
获得的循环局部结果中显式重新分配,例如
fn solverec (mut path: Path, mut pathtotal: f64, mut visited: Visited, mut since: Instant, mut bestpath: Path, mut besttotal: f64) -> (Path, Visited, Path, f64) {
// ...
let r = solverec(path, pathtotal, visited, since, bestpath, besttotal);
path = r.0;
visited = r.1;
bestpath = r.2;
besttotal = r.3;
I would recommend either extracting these to a single structure (possibly just a typedef eg type Solution = (Path, Visited, Path, f64)
) so they can be manipulated or reassigned as a unit rather than piecemeal, or restructuring the entire thing somehow.我建议要么将它们提取到单个结构中(可能只是一个 typedef,例如
type Solution = (Path, Visited, Path, f64)
),以便可以将它们作为一个单元而不是零碎地进行操作或重新分配,或者以某种方式重组整个事物。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.