计算选项默认值的惯用方法

问题描述 投票:0回答:1

我有一个读取配置文件的函数。如果用户选择将其设置为命令行参数,它会接收包含配置文件路径的

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

还有其他一些功能可以用来以更生锈的方式实现此代码吗?

rust
1个回答
0
投票

我不能使用

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)
})?;

(甚至可能需要更多类型注释。)

© www.soinside.com 2019 - 2024. All rights reserved.