简体   繁体   English

如何在 Rust 中使用递归 function 返回本地数据?

[英]How do I return local data with a recursive function in Rust?

I'm struggling to write a recursive algorithm in Rust.我正在努力在 Rust 中编写递归算法。 With the following code:使用以下代码:

use std::collections::HashMap;

enum Error {
    Bad,
    ReallyBad,
}

fn expand_symbols<'a, T: AsRef<str>>(
    symbols: &'a [T],
    ops: &HashMap<String, String>,
    user_ops: &'a HashMap<String, String>,
) -> std::result::Result<Vec<&'a str>, Error> {
    if symbols.iter().all(|x| ops.get(x.as_ref()).is_some()) {
        let symbols = symbols.iter().map(|x| x.as_ref()).collect();
        return Ok(symbols);
    }

    let mut expanded: Vec<&str> = vec![];
    for s in symbols {
        let s = s.as_ref();
        if ops.contains_key(s) || s.parse::<i32>().is_ok() {
            expanded.push(s);
        } else {
            let mut resolved = user_ops
                .get(s)
                .ok_or(Error::Bad)?
                .split_ascii_whitespace()
                .collect::<Vec<_>>();
            expanded.append(&mut resolved);
        }
    }
    expand_symbols(&expanded, ops, user_ops)
}

I get:我得到:

error[E0515]: cannot return value referencing local variable `expanded`
  --> src/main.rs:32:5
   |
32 |     expand_symbols(&expanded, ops, user_ops)
   |     ^^^^^^^^^^^^^^^---------^^^^^^^^^^^^^^^^
   |     |              |
   |     |              `expanded` is borrowed here
   |     returns a value referencing data owned by the current function

For more information about this error, try `rustc --explain E0515`.

However, if I change the last statement to:但是,如果我将最后一条语句更改为:

Ok(expanded)

it works, but it's not longer recursive.它有效,但不再是递归的。

I understand the idea that I'm trying to return a value borrowed from a local frame, but I think this is safe based on the second example.我理解我试图返回从本地框架借来的值的想法,但我认为基于第二个示例这是安全的。 How can I tell the compiler that?我怎么能告诉编译器呢?

Note: I'm using AsRef because I want to be able to pass both a Vec<String> and Vec<&str> to expand_symbols() .注意:我使用AsRef是因为我希望能够将Vec<String>Vec<&str>都传递给expand_symbols() Maybe I need to forget about that?也许我需要忘记这一点?

With Ok(expanded) the variable expanded is moved out of the function, meaning no reference to it existing after the function returned.使用Ok(expanded) expanded变量 expand 移出 function,这意味着在 function 返回后不存在对它的引用。 So, the second sample, if you meant by Ok(expanded) , is not same as the original one.因此,如果您指的是Ok(expanded) ,则第二个示例与原始示例不同。

To address the issue I think you can pass a mutable reference to symbols as the first parameter of the function, and do in-place edit on it instead of creating a new local vector, explanded .为了解决这个问题,我认为您可以传递对symbols的可变引用作为 function 的第一个参数,并对其进行就地编辑,而不是创建一个新的局部向量, explanded

fn expand_symbols<'a>(
    symbols: &'a mut Vec<&'a str>,
    ops: &HashMap<String, String>,
    user_ops: &'a HashMap<String, String>,
) -> std::result::Result<&'a Vec<&'a str>, Error> {
    if symbols.is_empty() || symbols.iter().all(|x| ops.get(*x).is_some()) {
         return Ok(symbols);
    }

    let mut unresolved: Vec<&str> = vec![]; 
    let mut i = 0;
    while i < symbols.len() {
        let s = symbols[i];
        if ops.contains_key(s) || s.parse::<i32>().is_ok() {
            i += 1;
        } else {
            unresolved.push(symbols.remove(i));
        }
    }

    for s in unresolved.iter() {
        let mut resolved = user_ops
            .get(*s)
            .ok_or(Error::Bad)?
            .split_ascii_whitespace()
            .collect::<Vec<_>>();
        symbols.append(&mut resolved);
    };

    expand_symbols(symbols, ops, user_ops)
}

playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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