Then it is no different from matches!(opt, Some(_))
(aside syntax)...
It wouldn't be the first time a language feature deprecated a library macro.
IIRC the other times a language feature replaced a macro (?
and async/await
being the ones I'm familiar with), there were at least some corner cases that the language feature handled better than any macro ever could, especially at scale when several uses of the feature were nested across several crates.
But is
and matches!
would be exactly identical in behavior, if I understand the current proposals correctly, so adding an is
keyword for this seems like a wash to me.
Sounds like it'd be nice to have a clippy lint that proposes to use matches!
instead of if let <pat> = <expr>
if the pattern has no bindings... at least I feel like that will always strictly improve readability. let
is very deeply connected with the idea of binding a name, at least in my brain. I always startle when I see things like if let <const> = <expr>
.
Yoda must have hit his head, though. if let 42 = x {}
"if let forty-two equals x"
Although it's kind of silly, you can even match on values in function arguments, if the values are irrefutable:
enum Foo {
TheOnlyVariant,
}
fn foo(Foo::TheOnlyVariant: Foo, (): ()) {}
It's not silly at all, but useful. For example, consider fn foo(Wrap(x): ...)
or fn foo((Ok(x) | Err(x): ...)
.
Yeah, so Rust managed to avoid the usual pitfall of if x = 42
, so it shouldn't need Yoda conditions... and yet we still have them. I don't think that's good.
It would probably make sense to continue allowing it for code generation purposes. Suddenly failing to compile Yoda patterns would probably introduce a non-uniformity that would in turn require many macro authors to come up with special cases.
Oh, I didn't suggest we disallow it. We also allow if 42 == x
, after all.
I just really dislike it being idiomatic for hand-written code.
I didn't mean the Yoda condition is good -- I was just amused to make the connection. Overall it's a natural edge case for pattern matching though. You can also write a constant let
when it's irrefutable, like let () = println!(...);
, which is only useful to statically assert the fact that it is constant.
I'm with this guy
I see a lot of questions about more complex syntax and determining scope and whatnot. What if we started by implementing only the minimum-viable syntax (if $expr is $pat {}
) and disallow anything more complex at first? This simple form has obvious semantics and would satisfy the 90% use-case right away, and we can worry about how/whether to extend it later.
This was the same approach taken for if let $pat = $expr {}
—we deferred dealing with &&
and other more complex syntax until later
Because that has no significant advantage over matches!()
.
Note that at this point the thread is very much repeating itself:
So someone with more free time than I currently have (sorry! Never mind, I completely missed that this is being stabilized. ) should probably put up an RFC that spells out the argument: "let's stabilize
matches!()
since everyone wants it, and no one's been able to come up with a compelling variable bindings story, or any other reason to provide this functionality via a new is
keyword".
matches!
is already stable in 1.42-beta.
It has no significant advantage in the same way as for
-loop has no significant advantage over an explicit loop
over an iterator. In other words: yes, it's a sugar construct, but which is significantly easier to type, read and perceive over matches!()
("natural to read" property is quite a nice one). Considering that it covers a sufficient fraction of use-cases, I believe at the very least it's a proposal worth consideration.
Personally I wouldn't be against it, but on my list of "nice to have" features it's quite low.
See:
Bindings are a significant improvement. To put it into code, with is
you can do this:
if opt is Some(x) {
println!("We got ourselves a {}", x);
}
Correct me if I'm wrong, but that's not possible with matches!()
. That is the shortcoming we're talking about.
But that can be done with if let
Yes, but now we're back to yoda conditionals.
if let 42 = x {}
I guess this really is going in circles I'll abstain.
So just use if let
with binders and matches!
without binders, then?
That seems like a reasonable approach to me, anyway.