Error handling 我是否可以简化处理选项的防锈代码<;T>;和结果<;T>;?

Error handling 我是否可以简化处理选项的防锈代码<;T>;和结果<;T>;?,error-handling,rust,optional,Error Handling,Rust,Optional,我正在开发我的第一个实际的Rust程序,一个定制的i3status。它进展顺利,但有两个地方我必须处理结果和选项,代码看起来非常难看,这让我相信我错过了一些语言特性或库函数来更清晰地编写这些部分 ,但我会在这里引用相关部分。第一个是: fn read_number_from_file(path: &str) -> Option<i64> { let mut file = match File::open(path) { Ok(f) => f

我正在开发我的第一个实际的Rust程序,一个定制的i3status。它进展顺利,但有两个地方我必须处理
结果
选项
,代码看起来非常难看,这让我相信我错过了一些语言特性或库函数来更清晰地编写这些部分

,但我会在这里引用相关部分。第一个是:

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,
    }
}
我觉得应该能够将每个
match
表达式压缩成一个函数调用,比如
。或_else()
,但是
。或_else(| return Vec::new())
显然不起作用,因为
return
的作用域是lambda而不是原始函数

因此,在这两种情况下,我的问题是,我是否可以用更简洁、更惯用的内容替换
match

要将
选项
s与
结果
s组合,请使用和问号操作符:

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()
}
或者仅仅因为:


对于第二部分,您可以使用crates.io like或上提供的其中一个理解板条箱。例如,对于,使用
map\u:

return map_for!(
    energy_full  <- read_number_from_file(ENERGY_FULL_PATH);
    energy_now   <- read_number_from_file(ENERGY_NOW_PATH);
    power_online <- read_number_from_file(POWER_ONLINE_PATH);
    is_charging  = power_online > 0;
    => vec![ energy_full, energy_now ]
).unwrap_or_else (|| vec![]);
returnmap\u for!(

能量已满,即使默认情况下,
STDERR
不可见,您仍然应该将错误记录到其中。它们甚至可能最终导致
~/.xsession错误
…如果您担心它可能变得嘈杂,您可以使用
调试!
日志
板条箱和朋友中进行调试。
.xsession错误
不会有任何帮助,因为我实际上正在使用Sway(即Wayland而不是X11),但你给了我一个想法,看看Sway是否将一个有用的stderr连接到status_命令进程。你不应该给它一个唯一的名称吗?对于第二部分,我们可以将所有代码移动到一个新函数
fn new_func(…)->选项
,旧函数将执行
new_func(…)。展开_或|其他(| vec![]))
@red75prime-answer更新;谢谢你的建议。顺便说一句,
unwrap(vec![])
unwrap\u或其他
一样好,因为空向量不分配。@aochagavia你的意思是
unwrap\u或(vec![])
,对吗?当然,我可以包含这些信息。@ljedrz是的,很抱歉给你带来混淆
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
}
let foo = foo().unwrap_or_else(|| vec![]);
let foo = foo().unwrap_or(vec![]);
return map_for!(
    energy_full  <- read_number_from_file(ENERGY_FULL_PATH);
    energy_now   <- read_number_from_file(ENERGY_NOW_PATH);
    power_online <- read_number_from_file(POWER_ONLINE_PATH);
    is_charging  = power_online > 0;
    => vec![ energy_full, energy_now ]
).unwrap_or_else (|| vec![]);