我正在使用带有自定义验证器的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_then
或Result
中的其他方法,如何简化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/