【问题标题】:How does this recursive join work in Rust这个递归连接如何在 Rust 中工作
【发布时间】:2020-10-27 05:47:28
【问题描述】:

所以我在 Rust 中编写了这个递归字符串连接函数,它似乎有效,但我有点困惑为什么它有效。

fn join(separator: &str, strs: &[&str]) -> String {
    match strs.len() {
        l if l > 1    => return strs[0].to_string() + separator + &join(separator, &strs[1..]),
        l if l == 1   => return strs[0].to_string(),
        _             => return "".to_string(),
    }
}

所以我有一个包含 3 个字符串的数组,我想加入一个字符串分隔符。该函数的第一个参数引用 str &str,第二个参数引用字符串数组 &[&str]

let j1 = ["one", "two", "three"];
println!("{}", join(", ", &j1));
  1. 为什么递归连接必须定义为&join(separator, &strs[1..])
  2. 为什么&strs[1..] 必须再次取消引用?

【问题讨论】:

    标签: recursion rust reference pass-by-reference


    【解决方案1】:
    1. std::ops::Add<&'_ str> is implemented for String(滚动到页面的最底部)。 std::ops::Add<String> 不是。因此,您只能将&'_ strs 添加到Strings,并且只能在右侧添加。您必须将您的调用引用到 join,因为它使用 deref 强制将 String 转换为 &str

    2. 这有点复杂,无法提供确切的证据,但简单来说,切片(使用索引位置中的范围)切片或数组将产生切片,IE,[T]。由于您不能到处乱转[T]s,因此您需要对其进行引用。
      更确切的原因是:


    此外,这不是编写此函数的最惯用方式:

    pub fn join(separator: &str, strs: &[&str]) -> String {
        match strs {
            [last]               => last.to_string(),
            [current, rest @ ..] => current.to_string() + separator + &join(separator, &rest),
            []                   => "".to_string(),
        }
    }
    

    Pattern matching works on slices.

    【讨论】:

      【解决方案2】:
      1. 为什么递归连接必须定义为&join(separator, &strs[1..])
        • + 运算符是std::ops::Add 的语法糖。
        • String 只有one Add implementationimpl<'_> Add<&'_ str> for String,这意味着你可以做String + &str 但不能做String + String
        • 由于join 返回String,您必须使用&join(...) 从结果中获得&str 才能使用+ 运算符。
      2. 为什么&strs[1..] 必须再次被取消引用?(我假设你的意思是,“为什么我不能只写strs[1..]?”)
        • 语法strs[1..] 的意思是“strs 包含的从索引 1 到结尾的值序列”。
        • 这个序列的长度,因此它的大小,在编译时是未知的,因此它不能被放置在堆栈上(它必须是为了用作函数的参数)。李>
        • 您没有将值放在堆栈上,而是取而代之的是对该值的引用,该值具有已知的大小。 (Rust 将此引用编译为“胖指针”,它由指向切片内存的指针和用于跟踪切片的长度值组成。)

      【讨论】:

        猜你喜欢
        • 2013-03-20
        • 2011-03-29
        • 1970-01-01
        • 2018-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多