Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Add a matches!(expression, pattern) macro. #163

Closed
wants to merge 2 commits into from

Conversation

SimonSapin
Copy link
Contributor

Rendered view: https://github.com/SimonSapin/rfcs/blob/matches-macro/active/0000-matches-macro.md

Please note: This is different from the if let proposal. I believe the two proposals are complementary rather than competing.

@SimonSapin
Copy link
Contributor Author

This was first proposed as rust-lang/rust#14685 and discussed by the team in the 2014-07-08 weekly meeting. The main concern there as far as I can tell was about adding things to the prelude. See the Alternatives part of this RFC for more discussion on this.


# Unresolved questions

Should this be a language feature rather than a macro? If so, what would the syntax look like?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the is operator that was discussed at the if let proposal.

The most reasonable version of it IMHO is that is is a keyword, and is an infix binary operator, where EXPRESSION is PATTERN is an expression of type bool and does basically the same thing as matches!(EXPRESSION, PATTERN), and doesn't allow binding names.

(This is intended as an answer to the second question, without implying any opinion about the first.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth noting that the benefit of matches!() over is is that matches!() can very easily allow for alternative patterns, as is being suggested here. However is cannot support alternative patterns without either being confusing (because | is a valid operator that one would expect to operate on the bool result of the is operator) or requiring additional syntax to enclose the set of patterns.

While I appreciate the syntactic simplicity of is, this suggests that matches!() may be the better approach (what with being implementable as a macro_rules! macro and not requiring the language grammar be extended in any way).

@netvl
Copy link

netvl commented Jul 14, 2014

+1 looks great! This is one of these small things which can make your life a lot nicer.

@lilyball
Copy link
Contributor

👍 I agree that this is complementary to if let, and I think it's potentially useful enough to justify placing in the prelude.

@Valloric
Copy link

This is both very useful and complementary to if let. There are several places in my codebase where I'd like to use this.

@huonw
Copy link
Member

huonw commented Jul 15, 2014

NB. this is a macro_rules! macro, so can easily be copy-pasted into codebases that wish to use it right now, and could even be provided as a Cargo plugin repository (possibly permanently, possibly temporarily, depending on the outcome of this RFC).

@esbullington
Copy link

This would be a very welcome addition. One comment: until I saw the macro itself, I was expecting matches! to produce something like an array of matches, instead of a boolean. To be explicit, I was interpreting matches! as a plural noun instead of a third-person verb.

RFC author proposes is_match! as a possible alternative syntax, and I believe this would remove the ambiguity I experienced initially. But either way, including it in prelude would be great.

@SimonSapin
Copy link
Contributor Author

@huonw What’s a Cargo plugin repository? It sounds related to the second alternative in the RFC.

@esbullington Yes, matches with an S is intended as a third-person verb, not a plural noun.

@asb
Copy link

asb commented Jul 16, 2014

I really like this proposal, and prefer the is_match! suggested alternative name.

@glaebhoerl
Copy link
Contributor

One consideration with respect to the question of whether a matches! macro, or a built-in is operator, would be preferable:

Having EXPR is PAT would make the various methods we currently provide such as is_some(), is_none(), is_ok(), is_err(), and so on totally redundant, and we could simply remove them.

Would we also be ready to remove them in favor of telling people to use matches!()?

@netvl
Copy link

netvl commented Jul 16, 2014

if some_expression.is_some() { ... }

versus

if some_expression is Some(_) { ... }

versus

if matches!(some_expression, Some(_)) { ... }

Personally I think that the last variant is totally ugly. is operator looks nice, though.

There is ambiguity problem with is, though.

enum X {
    A { x: int }
}

if some_expression is A { .. } { ... }

@glaebhoerl
Copy link
Contributor

@netvl I assume the same 'fix' could be applied as in some other points in the grammar with similar potential ambiguities, where struct literals (edit: or structural enum variants I guess) are disallowed except if wrapped in parentheses (IIRC). Perhaps someone more familiar with this could clarify.

@netvl
Copy link

netvl commented Jul 16, 2014

@glaebhoerl, yes, that would be quite natural. Just wanted to point this out.

@lilyball
Copy link
Contributor

I don't particularly like is_match!(). I think my preference would actually be for the simpler match!(). We don't allow keywords to be used when defining macro_rules! macros, but a syntax extension doesn't hit that issue, and I'm not sure if we have any such restriction on invoking a macro named after a keyword (I would hope not, as the trailing exclamation mark is typically considered part of the name). And if not match!(), I prefer matches!().

As for macro vs is, I like the syntactic simplicity of is, but there's no obvious way to allow for alternative patterns, and that seemed to be one of the desired features of matches!().

Regarding is_some() etc, I think it's reasonable for commonly-used generic enums like Option and Result to retain their existing methods for testing their variants. But lesser-used enums could then avoid having to define such functions if callers can be expected to have matches!() available to them.

@liigo
Copy link
Contributor

liigo commented Jul 16, 2014

How about match_single!?
Or even new syntax if exp match pat {}?
I personally like the later

@lilyball
Copy link
Contributor

@liigo The latter has no benefits over is. It still doesn't allow for alternates.

@glaebhoerl
Copy link
Contributor

@kballard I'm not deeply familiar with the grammer, but couldn't you just allow enclosing the RHS of is (the pattern) in parentheses to allow for using alternates?

@lilyball
Copy link
Contributor

@glaebhoerl You could certainly create a rule like that, but it just looks weird to me. Maybe it's not that bad, I don't know, but it's hard to argue that it's good when we could get the same functionality through a macro.

@lilyball
Copy link
Contributor

Basically, while I like the simplicity of is, and there are ways to come up with syntax to allow for pattern alternates, there's just not enough of a clear usability benefit over the macro approach to justify changing the grammar of the language.

@glaebhoerl
Copy link
Contributor

Yes, that was what I was thinking at first as well; while the possibility that is would let us get rid of all the is_* methods made me think again. If it's just "built-in is operator versus library-defined matches! macro", then yeah, why not the macro, but if it's "built-in is operator versus library-defined matches! macro plus having to provide is_* methods", then that's not so clear any more, because now the operator has concrete benefits alongside the nicer syntax. (Again, presuming you can just do if my_foo is (Some(true) | None) for disjunction, which doesn't look that bad to me.)

@treeman
Copy link

treeman commented Jul 17, 2014

Sounds good to me. I prefer matches! and match! over is_match!.

Visually this looks good to me:

if foo is Some(true) | None { ... }

but this might be confused with bit-wise or. If that's not possible I prefer the macro approach over is.

@blaenk
Copy link
Contributor

blaenk commented Jul 17, 2014

I think this is very useful. +1

@alexcrichton
Copy link
Member

This was discussed in today's weekly meeting, and the conclusion is that we would like to not merge this for now. We are primarily worried about adding such a feature to the prelude. We all very much desire a macro import/export system, and this RFC would likely be a shoo-in if we were to have one (so long as it were not in the prelude).

With that in mind, the decision was made to postpone this for now until such a system exists. Thanks for the RFC, however, @SimonSapin!

@mdinger
Copy link
Contributor

mdinger commented Oct 6, 2014

Visually, using an or instead of | to avoid conflict with bitwise operations looks nice. I suppose that would require | in match to change as well for consistency.
if some_expr is '+' or '-' { ... }

I saw that the benefit/change ratio might not be high (vs matches!) enough for this but I thought it might be useful to the discussion.

@SimonSapin
Copy link
Contributor Author

@SimonSapin
Copy link
Contributor Author

Nightly broke this, and it’s apparently not possible to fix without changing the usage syntax :( rust-lang/rust#20563 (comment)

@L-as
Copy link

L-as commented Jun 9, 2018

Since you can now use macros, perhaps this should be reopened?

@SimonSapin
Copy link
Contributor Author

The discussion in rust-lang/rust#35896 appears to be ongoing and not quite settled yet.

Also, this proposal is very old and I have limited bandwidth to champion it these days. Consider making a new RFC / PR. (Feel free to copy some or all of this one.)

@Centril Centril added A-patterns Pattern matching related proposals & ideas A-macros-libstd Proposals that introduce new standard library macros A-expressions Term language related proposals & ideas labels Nov 26, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-expressions Term language related proposals & ideas A-macros-libstd Proposals that introduce new standard library macros A-patterns Pattern matching related proposals & ideas postponed RFCs that have been postponed and may be revisited at a later time.
Projects
None yet
Development

Successfully merging this pull request may close these issues.