Is er een manier om het omzetten van een optie in een resultaat te vereenvoudigen zonder een macro?

Ik heb zoiets als dit (de echte functie is Ini::Section::getfrom rust-ini):

impl Foo {
    pub fn get<K>(&'a mut self, key: &K) -> Option<&'a str>
    where
        K: Hash + Eq,
    {
        // ...
    }
}

Ik moet het meerdere keren aanroepen:

fn new() -> Result<Boo, String> {
    let item1 = match section.get("item1") {
        None => return Result::Err("no item1".to_string()),
        Some(v) => v,
    };
    let item2 = match section.get("item2") {
        None => return Result::Err("no item2".to_string()),
        Some(v) => v,
    };
}

Om code bloat te verwijderen, kan ik een macro als volgt schrijven:

macro_rules! try_ini_get {
    ($e:expr) => {
        match $e {
            Some(s) => s,
            None => return Result::Err("no ini item".to_string()),
        }
    }
}

Is er een manier om de codeduplicatie te verwijderen zonder deze macro-implementatie?


Antwoord 1, autoriteit 100%

De ok_oren ok_or_else-methoden zetten Options om in Results, en de ?-operator automatiseert de standaardtekst die hoort bij vroege Errgeeft terug.

Je zou zoiets kunnen doen:

fn new() -> Result<Boo, String> {
    let item1 = section.get("item1").ok_or("no item1")?;
    let item2 = section.get("item2").ok_or("no item2")?;
    // whatever processing...
    Ok(final_result)
}

Antwoord 2

Als je de kist anyhowgebruikt, kun je de anyhow::Contexteigenschap die de .contextmethode toevoegt aan Options om ze om te zetten in anyhow::Results:

use anyhow::{Result, Context};
fn new() -> Result<Boo> {
    let item1 = section.get("item1").context("no item1")?;
    let item2 = section.get("item2").context("no item2")?;
    // whatever processing...
    Ok(final_result)
}

Other episodes