简体   繁体   English

Rust:关于递归 function 变异向量的指南

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM