Ik heb zoiets als dit (de echte functie is Ini::Section::get
from 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_or
en ok_or_else
-methoden zetten Option
s om in Result
s, en de ?
-operator automatiseert de standaardtekst die hoort bij vroege Err
geeft 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 anyhow
gebruikt, kun je de anyhow::Context
eigenschap die de .context
methode toevoegt aan Option
s om ze om te zetten in anyhow::Result
s:
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)
}