简体   繁体   English

这个递归连接如何在 Rust 中工作

[英]How does this recursive join work in Rust

So I wrote this recursive string join function in Rust which seems to work, but I'm a bit confused why it works.所以我在 Rust 中写了这个递归字符串 join function ,这似乎有效,但我有点困惑为什么它有效。

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(),
    }
}

So I have an array of 3 Strings that I would like to join and a String separator.所以我有一个要加入的 3 个字符串数组和一个字符串分隔符。 The function takes in the reference to a str &str for its first argument and then a reference to an array of Strings &[&str] for the second argument. function 的第一个参数引用一个 str &str ,第二个参数引用一个字符串数组&[&str]

let j1 = ["one", "two", "three"];
println!("{}", join(", ", &j1));
  1. Why does the recursive join have to be defined as &join(separator, &strs[1..]) ?为什么递归连接必须定义为&join(separator, &strs[1..])
  2. why does &strs[1..] have to be dereferenced again?为什么&strs[1..]必须再次取消引用?
  1. std::ops::Add<&'_ str> is implemented for String (scroll to the very bottom of the page). std::ops::Add<&'_ str>是为String实现的(滚动到页面的最底部)。 std::ops::Add<String> is not. std::ops::Add<String>不是。 Hence, you can only add &'_ str s to String s, and only on the right hand side.因此,您只能将&'_ str s 添加到String s,并且只能在右侧。 You have to reference your call to join because that uses deref coercion to turn the String into a &str .您必须引用您的join电话,因为它使用 deref 强制将String转换为&str

  2. This one is a bit more convoluted to provide exact evidence for, but in simplest terms, slicing (using a range in the index position) a slice or array will produce a slice, IE, [T] .这有点复杂,无法提供确切的证据,但用最简单的术语来说,切片(使用索引位置中的范围)切片或数组将产生切片,IE, [T] Since you can't pass around bare [T] s around, you need to take a reference to it.由于您无法传递裸露的[T] ,因此您需要对其进行引用。
    The more exact reason as to why is:更确切的原因是:


Additionally, this isn't the most idiomatic way of writing this function:此外,这不是编写此 function 的最惯用的方式:

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. 模式匹配适用于切片。

  1. Why does the recursive join have to be defined as &join(separator, &strs[1..]) ?为什么递归连接必须定义为&join(separator, &strs[1..])
    • The + operator is syntactic sugar for std::ops::Add . +运算符是std::ops::Add的语法糖。
    • String has only one Add implementation , impl<'_> Add<&'_ str> for String , which means you can do String + &str but not String + String . String只有一个Add实现impl<'_> Add<&'_ str> for String ,这意味着你可以做String + &str但不能做String + String
    • Since join returns a String , you have to get a &str from the result with &join(...) in order to use the + operator.由于join返回一个String ,您必须使用&join(...)从结果中获取一个&str才能使用+运算符。
  2. Why does &strs[1..] have to be dereferenced again?为什么&strs[1..]必须再次取消引用? (I'm assuming you mean, "why can't I just write strs[1..] ?") (我假设你的意思是,“为什么我不能只写strs[1..] ?”)
    • The syntax strs[1..] means "the sequence of values contained by strs from index 1 to the end".语法strs[1..]表示“ strs包含的从索引 1 到末尾的值序列”。
    • The length of this sequence, and therefore its size, is not known at compile time, and so it cannot be placed on the stack (which it must be in order to be used as an argument to a function).这个序列的长度,因此它的大小,在编译时是未知的,因此它不能放在堆栈上(它必须放在堆栈上才能用作函数的参数)。
    • Instead of placing the value on the stack, you take a reference to the value instead, which has a known size.不是将值放在堆栈上,而是对具有已知大小的值进行引用。 (Rust compiles this reference as a "fat pointer" which consists of a pointer to the slice memory and a length value to keep track of the slice.) (Rust 将此引用编译为“胖指针”,它由指向切片 memory 的指针和用于跟踪切片的长度值组成。)

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

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