我有一个读取配置文件的函数。如果用户选择将其设置为命令行参数,它会接收包含配置文件路径的
Option<String>
作为参数。如果未定义,该函数将使用用户主目录(home
crate)与默认文件名连接来计算默认路径。这段代码可以工作,但是 match
看起来有点像 Rust 中必须有一些更惯用的方法来解决这个问题。我无法使用 unwrap_or()
,因为它不允许计算默认路径所需的多个语句。
fn get_config(config_file: Option<String>) -> Result<Config, Box<dyn std::error::Error>> {
let credentials_path = match config_file {
None => {
let mut default_path = (home::home_dir()).ok_or_else(||{"Can not find home directory"})?;
default_path.push("credentials.toml");
default_path
},
Some(s) => s.into(),
};
println!("path: {:?}", credentials_path);
let contents = std::fs::read_to_string(credentials_path)?;
let config: Config = toml::from_str(contents.as_str()).unwrap();
Ok(config)
}
还有其他一些功能可以用来以更生锈的方式实现此代码吗?
我不能使用
,因为它不允许计算默认路径所需的多个语句。unwrap_or()
您可以在 Rust 中的任何表达式中使用块(同样,闭包的主体是任何表达式,不一定是块):
let credentials_path = config_file.map(|p| p.into()).unwrap_or({
let mut default_path = home::home_dir().ok_or_else(|| "Cannot find home directory")?;
default_path.push("credentials.toml");
default_path
});
unwrap_or_else
),以及 .map
into
和从返回的 ?
运算符的组合,最好不要评估该块与这种模式相比,外部函数使 match
成为一个相对干净的选项:
let credentials_path = config_file.map(|p| Ok(p.into())).unwrap_or_else(|| {
let mut default_path = home::home_dir().ok_or("Cannot find home directory")?;
default_path.push("credentials.toml");
Ok(default_path)
})?;
(甚至可能需要更多类型注释。)