"If" statement using Result<T,E> value

Hi, I'm using Arkworks to write Groth16-style zkSNARKs in Rust. I have the following code that doesn't work.

let has_signature_wtns = Boolean::<P::Fp>::new_witness(cs.clone(), || self.has_signature.as_ref().ok_or(SynthesisError::AssignmentMissing))?;
if has_signature_wtns.value().is_some() { // do something}

has_signature is an Option<> variable, and the return value of new_witness is Result<> so has_signature_wtns is either Err or a witness variable in Groth16. I want to do something if has_signature_wtns has an actual value and not an error. Is there a way to achieve this?

If it helps, this is the new_witness function:

fn new_witness<T: Borrow<V>>(
        cs: impl Into<Namespace<F>>,
        f: impl FnOnce() -> Result<T, SynthesisError>,
    ) -> Result<Self, SynthesisError> {
        Self::new_variable(cs, f, AllocationMode::Witness)
    }

fn new_variable<T: Borrow<V>>(
        cs: impl Into<Namespace<F>>,
        f: impl FnOnce() -> Result<T, SynthesisError>,
        mode: AllocationMode,
    ) -> Result<Self, SynthesisError>;
1 Like

What do you mean "doesn't work"? Do you get a compiler error, or does the code not produce the expected behaviour?

How about:

if let Ok(signature) = has_signature_wtns.value() {
    // do something with variable `signature`
}

Not able to test it out right now though.

This worked! Thank you so much!

1 Like

Of course, no problem! Just a fellow hobbyist. You can mark my answer as the solution if you want. :slight_smile:

Also, some further information:

The Result<> type can be either Ok<foo> or Err<bar>, while the Option<> type can be Some<foo> or None. The Ok, Err, and Some variants each hold a value.

When your function returns a Result<>, the enum will be either Ok with the variable you want, or Err with a different value specifying the error. You need to check if the result is Ok<something>, and if so, get the inner type. If you read the official rust book (link) I believe there is a section of multiple ways of doing this. A common way of doing it if it's a small project is calling .except("your error here") on the function itself which automatically make sure it's an Ok value. If not, it immediately crashes (panics) the program with the error message.

There is also ?.

? will diverge (returning from the function) with the Err if it is one, and evaluates to the value inside the Ok otherwise.

let val = result?;

// use val here, it is not wrapped in Ok.

This is similar to doing:

match result {
    Ok(val) => {
        // use val here, it is not wrapped in Ok.
    }
    error => return error
}

The difference being that ? also transforms the error type into the type returned by the function using a From implementation. Which might sound confusing, but it's useful :slight_smile:

? only works if the function containing it returns a Result.

No, it also works for Option<_>, ControlFlow<_, _>, and some Poll<_>s. And hopefully custom types too, eventually.

4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.