Rust 中字符串连接的归约与折叠

Lar*_*aug 10 functional-programming rust

从 1.51 开始,Rust 就包含了reduce,我在 Scala 中已经习惯了。 fold与 Scala 中的 FoldLeft 类似,但reduce 不同。我错了什么?

这工作得很漂亮:

let ss = vec!["a", "b", "c"].iter()
.fold("".to_string(), |cur, nxt| cur + nxt);

println!("{}", ss);
Run Code Online (Sandbox Code Playgroud)

这不会:

let ss = vec!["a", "b", "c"].iter()
.reduce(|cur, nxt| cur + nxt);

println!("{}", ss);
Run Code Online (Sandbox Code Playgroud)

错误:

let ss = vec!["a", "b", "c"].iter()
.fold("".to_string(), |cur, nxt| cur + nxt);

println!("{}", ss);
Run Code Online (Sandbox Code Playgroud)

(操场)

我究竟做错了什么?

Joh*_*ica 14

在第一个中,您从"".to_string()拥有的String. String实现Add<&'_ str>允许您&str使用运算符连接其他借用的字符串+

写出参数类型可以让您清楚地看到cur和之间的区别nxt

let ss = vec!["a", "b", "c"].iter()
    .fold("".to_string(), |cur: String, nxt: &&str| cur + nxt);
Run Code Online (Sandbox Code Playgroud)

reduce()另一方面,该调用纯粹适用于&strs,但&str不支持与 的串联+。没有任何Add暗示。

let ss = vec!["a", "b", "c"].iter()
    .reduce(|cur: &str, nxt: &str| cur + nxt); // &str + &str not defined
Run Code Online (Sandbox Code Playgroud)

虽然&str不支持串联,String但支持串联,因为它可以高效地完成串联。a + b消耗a,重新使用其缓冲区来获取结果String。它不必分配O(a.len())空间,也不必花O(a.len())时间复制a. 只是简单地附加到 的缓冲区b中。a

因此,如果将借用的&strs 转换为拥有的Strings,它会编译:

let ss = vec!["a", "b", "c"].iter()
    .map(|s| s.to_string())
    .reduce(|cur: String, nxt: String| cur + &nxt)
    .unwrap();
Run Code Online (Sandbox Code Playgroud)

另请注意,它reduce()返回一个Option<String>需要解包的对象。