Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to simplify converting an Option into a Result without a macro?

Tags:

rust

I have something like this (the real function 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,     {         // ...     } } 

I have to call it several times:

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,     }; } 

To remove code bloat, I can write a macro like this:

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

Is there any way to remove the code duplication without this macro implementation?

like image 214
fghj Avatar asked Jun 17 '16 21:06

fghj


People also ask

What is unwrap() in Rust?

To “unwrap” something in Rust is to say, “Give me the result of the computation, and if there was an error, panic and stop the program.” It would be better if we showed the code for unwrapping because it is so simple, but to do that, we will first need to explore the Option and Result types.

What does OK Do Rust?

It is an enum with the variants, Ok(T) , representing success and containing a value, and Err(E) , representing error and containing an error value. Functions return Result whenever errors are expected and recoverable. In the std crate, Result is most prominently used for I/O.

What is option Rust?

Type Option represents an optional value: every Option is either Some and contains a value, or None , and does not. Option types are very common in Rust code, as they have a number of uses: Initial values. Return values for functions that are not defined over their entire input range (partial functions)


2 Answers

The ok_or and ok_or_else methods convert Options to Results, and the ? operator automates the boilerplate associated with early Err returns.

You could do something like:

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) } 
like image 120
pyon Avatar answered Sep 22 '22 19:09

pyon


If you're using the crate anyhow you can import the anyhow::Context trait which adds the .context method on Options to turn them into 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) } 
like image 23
orlp Avatar answered Sep 21 '22 19:09

orlp