rust - 使用 `and_then`如何返回Result <(),String>

标签 rust

我正在使用带有自定义验证器的clap,如下所示:

.arg(
    Arg::with_name("config")
       .help("config.yml")
       .long("config")
       .default_value("config.yml")
       .short("c")
       .required(true)
       .value_name("FILE")
       .validator(is_file),
    )

这是我正在使用的工作验证程序is_file:

fn is_file(s: String) -> Result<(), String> {
    let metadata = match metadata(&s) {
        Err(err) => return Err(err.to_string()),
        Ok(metadata) => metadata,
    };
    if !metadata.is_file() {
        return Err(format!("cannot read file: {}", s));
    }
    Ok(())
}

阅读有关 std::result::Result 的更多信息后,我发现它具有多种方法,可用于简化或显着减少代码。

为了简化is_file我正在尝试:

fn is_file(s: String) -> Result<(), String> {
   metadata(&s).and_then(|m| (!m.is_file()))
}

我的问题是!m.is_file()返回bool:

 metadata(&s).and_then(|m| !m.is_file())
   |                               ^^^^^^^^^^^^
   |                               |
   |                               expected enum `std::result::Result`, found `bool`
   |                               help: try using a variant of the expected enum: `Ok(!m.i


使用and_thenResult中的其他方法,如何简化is_file函数?

最佳答案

您需要自己创建Result,但是您可以使用问号运算符和map_err()删除match语句:

fn is_file(s: String) -> Result<(), String> {
    if metadata(&s).map_err(|e| e.to_string())?.is_file() {
        Ok(())
    } else {
        Err(format!("cannot read file: {}", s))
    }
}

或按照您的建议使用and_then():
fn is_file(s: String) -> Result<(), String> {
    metadata(&s).map_err(|e| e.to_string()).and_then(|m| {
        if m.is_file() {
            Ok(())
        } else {
            Err(format!("cannot read file: {}", s))
        }
    })
}

我想说这是否比您的原始代码更好。

将来,如果有类似then_some() Result ,您可能可以不用if-else编写它。

关于rust - 使用 `and_then`如何返回Result <(),String>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61933282/

相关文章:

rust - 不能在 Rc 中借用为可变的

rust - From 特征的实现可以是有损的吗?

rust - 不能在循环中多次借用可变错误

rust - 是否可以使用 Clap 配置未知大小的参数组?

rust - 有没有办法从 travis-ci 构建下载编译工件?

rust - 为什么带有保护子句的匹配模式不是详尽无遗的?

pattern-matching - Rust 模式匹配中的负零

xpath - 如何使用 SXD-XPath 遍历节点集并打印出每个值?

functional-programming - 迭代连续折叠结果的惯用和功能方法是什么?

generics - 名称 `T`已用于通用参数