Try_then method for bool

impl bool {
  fn try_then<T, E>(self, f: impl FnOnce() -> Result<T, E>) -> Result<Option<T>, E> {
    self.then(f).transpose()
  }
}

That method is needed when you want to use bool::then, but your closure returns Result, and you must use .transpose()? to propagate error to the calling function

1 Like

Can you give an example of this coming up in practice?

yes, I was writing a parser, and this piece of code looked suspiciously capable of being rewritten using standard methods,

image

however, the fact that Block::parse returns Result prevented me from doing this very well

What's the problem with the transpose() call in the calling code?

3 Likes

it adds 1 extra line of code

In my opinion, the original if-else code is really nice and readable, while the transpose, but also a try_then, would require me to think more, not really making the code nicer but only more confusing. You can also remove the outer (pink) block, which will cut down two more lines from the original if-else code.

1 Like

.transpose() makes that second variant harder to comprehend, so try_then, thanks to the clear name, would make the code more understandable and short

2 Likes

I'd probably write that as a match, which is pretty nice IMO:

let else_body = match token_stream.try_consume(TokenValue::Else) {
    true => Some(Block::parse(token_stream)?),
    false => None,
};

This is just four lines (similar to your .then(..).transpose()?) option, but much easier to follow.

2 Likes