1

I have a function, that returns Option<Result<X, String>> and it calls some functions that return Result<Y, String>. How is it possible to use the ? operator in a way, that it wraps the error in a Some?

fn other_func() -> Result<Y, String> {
    // ...
}

fn my_func() -> Option<Result<X, String>> {
    // ...
    let value = other_func()?;
    // ...
}

I have two problems:

  • I do not know how to wrap ? in Some
  • Result<X, String> is different from Result<Y, String>, but since I only care about the error at that point, it should not matter

I am able to solve it with combining match and return, but I would like to use ? if it is possible somehow. This is my current solution:

let value = match other_func() {
    Ok(value) => value,
    Err(msg) => return Some(Err(msg))
};
Iter Ator
  • 8,226
  • 20
  • 73
  • 164
  • 2
    `Option>` seems like an anti-pattern; it would make more sense to return `Result – kaya3 Nov 10 '22 at 17:41
  • If I implement an iterator for example it is always Optional where T could be Result, not the other way around – Iter Ator Nov 10 '22 at 17:46
  • 3
    I agree with kaya3. The two types are isomorphic but `Result – Silvio Mayolo Nov 10 '22 at 18:18
  • If you have an iterator over results, you probably do not want to continue after there is an error; but `Some(Err(...))` would signal that the iteration is not necessarily completed yet. See [this Q&A](https://stackoverflow.com/q/36368843/12299000) and [this one](https://stackoverflow.com/q/26368288/12299000). – kaya3 Nov 10 '22 at 18:19

2 Answers2

3

This isn't possible using the ? operator, you would have to do what your current solution is.

Here is some info on what the ? operator does: https://doc.rust-lang.org/rust-by-example/std/result/question_mark.html - it is just syntactic sugar around

match <expr> {
  Ok(val) => val,
  Err(err) => {
    return Err(From::from(err))
  }
}

so the only way to wrap your Err in Some(err) is by manually matching as you've done.

Tyler Aldrich
  • 386
  • 2
  • 10
0

You can use a helper function or closure that returns Result<Option<X>, String>, and then call transpose(). For example:

fn my_func() -> Option<Result<X, String>> {
    (|| -> Result<Option<X>, String> {
        // ...
        let _value = other_func()?;
        // ...
        Ok(None)
    })()
    .transpose()
}

If this use of closure is too obscure, you can simply define an inner fn helper() and call helper().transpose() (or define the helper outside my_func).

user4815162342
  • 141,790
  • 18
  • 296
  • 355