【问题标题】:Rust: guidance on recursive function mutating vectorsRust:递归函数变异向量指南
【发布时间】:2021-04-27 08:13:51
【问题描述】:

我需要一些指导如何处理需要改变从先前递归级别提供给它的向量的递归函数。

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!();
}

编译器抱怨很多:

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

【问题讨论】:

  • 将您的 solverec 函数更改为 fn solverec (path: &amp;mut Path, pathtotal: f64, visited: &amp;mut Visited, since: Instant, bestpath: &amp;Path, besttotal: f64) -&gt; (&amp;Path, f64) 以便它可以改变其参数。
  • 不要用你的解决方案编辑你的问题;这会使问题、答案的上下文无效,并自行将其打开以关闭(因为它不再是问题了)。如果您有其他信息,请添加它 - 不要更改您可用的信息,除非您可以以不会导致答案无效的方式这样做。如果您有完整的答案,post one(鼓励)

标签: arrays recursion rust borrow-checker


【解决方案1】:
        let (path, visited, bestpath, besttotal) = solverec(path, pathtotal, visited, since, bestpath, besttotal);

这会消耗 4 个函数局部变量,并使用 4 个 循环局部 变量来隐藏它们。

所以循环只能执行一次,之后就没有任何用处了:循环局部变量在循环结束时被丢弃

您可能曾尝试使用它,因为大规模重新分配

(path, visited, bestpath, besttotal) = ...

没用。

遗憾的是,不,它没有,重新分配不是模式,因此您不能使用解构重新分配,并且没有重新声明不能解决它。您必须创建函数本地绑定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;

我建议将它们提取到单个结构中(可能只是一个 typedef,例如 type Solution = (Path, Visited, Path, f64)),以便可以将它们作为一个单元而不是零碎地进行操作或重新分配,或者以某种方式重组整个事物。

【讨论】:

  • 我采纳了您的建议并将其减少为一个错误。你能再看看吗?
  • 错误似乎很明显。当您致电solverec 时,您移动 bestpath 进入其中。但是你只能有条件地重新分配它。当besttotal2 &gt;= besttotal 时会发生什么?
  • 你几乎解决了它。将使用工作代码更新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
  • 2015-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
相关资源
最近更新 更多