4

As far as I can tell, refutable patterns can only be tested in match, if let, and while let expressions. To illustrate what I would like to do, consider the use of the => syntax from the match statement in the following context:

let val = get_optional_value();
if val => Some(inner) {
    do_something(inner);
}

I could use an if let statement, but a more useful context would be in short closures:

get_optional_value()
    .filter(|iv| iv => InnerVariant::VariantA)
    .and_then(/* ... */)

As far as I can tell, the only solution to achieving this using pattern matching would be:

get_optional_value()
    .filter(|iv| {
        if let InnerVariant::VariantA = iv {
            true
        } else {
            false
        }
    })
    .and_then(/* ... */)

There is a similar question that did not get answered but the comments do point to the use of the ? operator that solves a related corner case for std::result::Result.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
mallwright
  • 1,670
  • 14
  • 31
  • I don't really see usecase in your example. what would you do in `and_then` ? cause you need to match again your variant. – Stargateur Jul 01 '20 at 11:15
  • I think there are use cases here but the `and_then` in this example was more to illustrate that if you have chain of methods that take closures this would become very verbose. – mallwright Jul 01 '20 at 11:36
  • 1
    It's hard to answer multiple questions made in one post. Please separate them into multiple questions so that we can help you better and so that your questions will help others in the future that have one of the same questions as you! I've deleted the unrelated question. – Shepmaster Jul 01 '20 at 13:13
  • Yes, I was thinking about removing that bit and putting it in its own question... thanks! – mallwright Jul 01 '20 at 13:53

1 Answers1

9

Rust 1.42 added the matches! macro. matches!(X, Y) returns a boolean indicating whether expression X matches the pattern Y.

In your case, it could be used like this:

get_optional_value()
    .filter(|iv| matches!(iv, InnerVariant::VariantA))
    .and_then(/* ... */)

This does not let you bind new names, you can only access the "inner" data in an optional if guard.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
justinas
  • 6,287
  • 3
  • 26
  • 36