我正在编写一种方法来遍历地图的(from, to)
并执行多轮tmp = tmp.replace(from, to)
。我仍在努力掌握Rust的所有权概念
#[macro_use]
extern crate lazy_static;
use std::collections::HashMap;
lazy_static! {
static ref REPLACEMENTS: HashMap<&'static str, &'static str> = {
let mut m = HashMap::new();
m.insert("abc", "def");
m.insert("com", "org");
m
};
}
fn replace_path_name(path: &str) -> &str {
let mut tmp = path;
for (from, to) in REPLACEMENTS.iter() {
let a = *from;
let b = *to;
tmp = tmp.replace(a, b);
}
tmp
}
fn main() {}
这段代码让我......
error[E0308]: mismatched types
--> src/main.rs:22:15
|
22 | tmp = tmp.replace(a, b);
| ^^^^^^^^^^^^^^^^^
| |
| expected &str, found struct `std::string::String`
| help: consider borrowing here: `&tmp.replace(a, b)`
|
= note: expected type `&str`
found type `std::string::String`
额外的a
和b
是我尝试了解Rust为什么from
和to
成为&&str
。
答案 0 :(得分:1)
第一个问题是您的返回值:&str
。您正在返回对某些内容的引用,但拥有该值的内容是什么?您不能返回对局部变量的引用。
第二个问题是str::replace
的返回类型,它是String
,而不是&str
。这是您的错误消息的原因:您试图将String
存储在只能存储&str
的变量中。你不能这样做。
最简单的修复不是最有效的;只需创建一个String
:
fn replace_path_name(path: &str) -> String {
let mut tmp = String::from(path);
for (from, to) in REPLACEMENTS.iter() {
tmp = tmp.replace(from, to);
}
tmp
}
在某些情况下,您还可以使用类似Cow
的类型来节省一些分配:
use std::borrow::Cow;
fn replace_path_name(path: &str) -> String {
let mut tmp = Cow::from(path);
for (from, to) in &*REPLACEMENTS {
tmp = tmp.replace(from, to).into();
}
tmp.into()
}
甚至可以返回哪个,以便在没有替换时不会发生分配:
use std::borrow::Cow;
fn replace_path_name(path: &str) -> Cow<str> {
let mut tmp = Cow::from(path);
for (from, to) in &*REPLACEMENTS {
tmp = tmp.replace(from, to).into();
}
tmp
}
令人遗憾的是str::replace
没有返回Cow<str>
。如果确实如此,如果没有替换则不会进行任何分配。
另见: