How to get value from Result<Option<T>, Error>?

Hi, folks. Is there a better way to get value out from Result<Option> wrapper?

Something like this:

A function return Result<Option<Vec<u8>>>

fn get(&self, xx, xx) -> -> Result<Option<Vec<u8>>, DatabaseError> {
       // some thing
}

Later in another file, I wanted to get the value of Vec<u8> and avoid panicing. I had try this way:

let result = self
            .get(xx, xx)
            .map(|i| i.unwrap())
            .map(|e| function(&e))
            .unwrap();

Another issue:

Can anybody explain the concrete different usage between map and and_then?

Both do the same, nearly.

map comes from the Iterator trait while and_then is implemented on the Option struct.

Basically the difference is in the return type and where you can use them.

Both map and and_then are methods on both Option and Result. The difference is that with and_then you can return None or Err in the closure.

1 Like

They are similar, but not the same.
The argument op: F has different return type.
They can achieve same function indeed.

pub fn map<U, F>(self, op: F) -> Result<U, E>
where
    F: FnOnce(T) -> U, 
pub fn and_then<U, F>(self, op: F) -> Result<U, E>
where
    F: FnOnce(T) -> Result<U, E>, 

O, wait? Does this mean, that and_then is the monadic bind? Nice to know!

2 Likes

Yep! That is the rust naming convention for monadic bind operations when it involves a single item. You'll also find an and_then on things like Future. If there are several items (e.g. Iterator) they will typically call it flat_map.

2 Likes

.unwrap() is for panicking, so you can't use it, unless you want to cause a panic.

When you have Result, you should try to use ? on it:

let option = optionresult?;

and then proceed to how you'd handle the option.

If None is an error, then:

let value = option.or_or(Error::StuffIsMissing)?; // make the error type yourself

If you don't care about errors, just want to get the value, then:

if let Ok(Some(value)) = optionresult {
}

or if you want to handle all errors and None in the same way:

let optionoption = optionresult.ok(); // strips the error out
let option = optionoption.and_then(|x| x); // changes Option<Option<T>> to Option<T>
let value = option.unwrap_or_default(); // there's a bunch more graceful unwrap versions
2 Likes

Thanks a lot.