Ste*_*sky 3 error-handling optional rust
我正在研究我的第一个实际的Rust程序,一个自定义的i3status.它很顺利,但有两个地方我必须处理,Result<T>而且Option<T>代码看起来非常难看,让我相信我错过了一些语言功能或库函数来更清晰地编写这些部分.
这是有问题的文件,但我会在这里引用相关部分.第一个是:
fn read_number_from_file(path: &str) -> Option<i64> {
let mut file = match File::open(path) {
Ok(f) => f,
Err(_) => return None,
};
let mut contents = String::new();
match file.read_to_string(&mut contents) {
Ok(_) => {},
Err(_) => return None,
};
match contents.trim().parse::<i64>() {
Ok(val) => Some(val),
Err(_) => None,
}
}
Run Code Online (Sandbox Code Playgroud)
这里吞咽错误信息是故意的.i3status没有stderr,所以我所能做的就是跳过渲染损坏的部分.
无论如何,这段代码看起来很丑陋,重复使用它match来丢弃Err值.我尝试?通过使返回类型为a 来使用new 运算符std::io::Result<i64>,但str::parse返回不同类型的错误,因此AFAICS不起作用.因此,我选择Option<i64>了最低标准.
第二个丑陋的部分是使用此函数的地方:
let energy_full = match read_number_from_file(ENERGY_FULL_PATH) {
Some(val) => val,
None => return Vec::new(),
};
let energy_now = match read_number_from_file(ENERGY_NOW_PATH) {
Some(val) => val,
None => return Vec::new(),
};
let is_charging = match read_number_from_file(POWER_ONLINE_PATH) {
Some(val) => val > 0,
None => return Vec::new(),
};
Run Code Online (Sandbox Code Playgroud)
我觉得应该能够将每个match表达式收缩到函数调用中.or_else(),但.or_else(|| return Vec::new())显然不会起作用,因为return它的作用域是lambda而不是原始函数.
所以,在这两种情况下,我的问题是我是否可以用match更紧凑和惯用的东西来代替.
要将Option<T>s与Result<T, E>s 组合,请使用ok()和问号运算符:
fn read_number_from_file(path: &str) -> Option<i64> {
let mut file = File::open(path).ok()?;
let mut contents = String::new();
file.read_to_string(&mut contents).ok()?;
contents.trim().parse::<i64>().ok()
}
Run Code Online (Sandbox Code Playgroud)
至于问题的第二部分,如果你可以在一个函数中包含所有这些变量绑定:
fn foo() -> Option<Vec<i64>> { // or some other Option<Vec>
let energy_full = read_number_from_file(ENERGY_FULL_PATH)?;
let energy_now = read_number_from_file(ENERGY_NOW_PATH)?;
let is_charging = read_number_from_file(POWER_ONLINE_PATH)? > 0;
Some(Vec::new()) // placeholder for the valid return value
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用unwrap_or_else()其结果Vec在任何错误时返回空:
let foo = foo().unwrap_or_else(|| vec![]);
Run Code Online (Sandbox Code Playgroud)
或者只是unwrap_or(),因为空向量不分配内存:
let foo = foo().unwrap_or(vec![]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
556 次 |
| 最近记录: |