-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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: ?
repetition in macro rules
#2298
Conversation
?
repetition in macro rules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea in general and I would love to have this in the language. I have some minor stylistic suggestions tho (I hope you don't mind those..) as well as an improvement idea for the Motivation-section.
text/0000-macro-at-most-once-rep.md
Outdated
|
||
Motivation | ||
---------- | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another motivation you could add is an argument from familiarity with regular expressions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mention this in the rationale as a reason why ?
was chosen, but since the RFC explicitly chooses to not add {M, N}
, I think it would be hard to add familiarity with regexes to the motivation.
I think this is a great idea - the trailing commas thing in particular has always irritated me, given that rustfmt favours them using them for structs/enums/etc. I do wonder if using |
@Centril Thanks for the comments! I tried to address them in the latest commit. Specifically:
|
I thought about this a bit too. However, the use of |
|
@Ixrec Yeah, it's not a huge issue ("if a |
text/0000-macro-at-most-once-rep.md
Outdated
--------- | ||
While there are grammar ambiguities, they can be easily fixed, as noted by @kennytm [here](https://internals.rust-lang.org/t/pre-rfc-at-most-one-repetition-macro-patterns/6557/2?u=mark-i-m): | ||
|
||
> There is ambiguity: $($x:ident)?+ today matches a?b?c and not a+. Fortunately this is easy to resolve: you just look one more token ahead and always treat ?* and ?+ to mean separate by the question mark token. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should better be put back to reference-level explanation. You cannot implement ?
without clarifying this bit.
@kennytm I moved the note on ambiguity back to the reference section, but left a note in drawbacks. |
I'd just like to mention, since this didn't come up yet, that besides |
@Apanatshka You can build "two or more" with |
Also, I think |
Is there any way to request an FCP for this? It's not a very big feature and seems to have wide support. I don't want it to be forgotten... |
@mark-i-m '''@Apanatshka You can build "two or more" with pat1 pat2 $(more)*, but I don't think you can build it with {m,n}.''' Generalized {m,n} would allow:
If you followed the same rules as for Regex. |
@rfcbot fcp merge Is there an ambiguity like That said, I bang my head against this all the time. I think that having We should address who will implement it (or mentor an implementation of it). |
Team member @nikomatsakis has proposed to merge this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
@nikomatsakis You typed Yes there is ambiguity, but it is already acknowledged in the RFC with a way to workaround it, so it is not a problem. |
@nikomatsakis I have already started implementing: rust-lang/rust@master...mark-i-m:at-most-once-rep |
Also, it would be nice (though not necessary) if rust-lang/rust#47732 and rust-lang/rust#47603 were merged before the implementation of this feature (purely for code cleanliness)... |
Also, cc @ExpHP, who I believe, went around adding trailing comma support to a bunch of macros in |
Ah, I forgot about that! I enumerated all the places they're missing but haven't actually fixed them yet. 😛 I'm glad to see this is already on the track to acceptance. I'd think I'd be hard pressed to find somebody who has written macros and hasn't wanted something like this from day one. |
I'm somewhat reluctant to extend the macro pattern language before we decide if and how the pattern language should change for macros 2.0. But, I guess it is nice to experiment with it since we don't have any firm plans, and I assume this could be left unstable for some time. |
@nrc Could you be a bit more specific about your concerns? For example, do you feel that adding this will complicate macros 2.0 somehow? |
Made a tracking issue since we plan to land the implementation before FCP is complete: |
So the breaking change proposal would also not accept a separator with
`$(pat)?`, right?
…On Thu, Feb 8, 2018 at 1:08 PM, Niko Matsakis ***@***.***> wrote:
Made a tracking issue since we plan to land the implementation before FCP
is complete:
rust-lang/rust#48075 <rust-lang/rust#48075>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2298 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAC3n6wncWx60qFnMSNfbYXOPj5c1hzcks5tSzgogaJpZM4RhtUf>
.
|
I'm just not sure this rises to the level of breaking changes. It's not a
high-priority bug fix or anything. Yeah it's a feature that should've been
included from the beginning, but we shouldn't set the precedent of doing
breaking changes like that whenever we think they can fly under the radar.
…On Thu, Feb 8, 2018 at 1:15 PM, Alex Burka ***@***.***> wrote:
So the breaking change proposal would also not accept a separator with
`$(pat)?`, right?
On Thu, Feb 8, 2018 at 1:08 PM, Niko Matsakis ***@***.***>
wrote:
> Made a tracking issue since we plan to land the implementation before FCP
> is complete:
>
> rust-lang/rust#48075 <rust-lang/rust#48075>
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <#2298 (comment)>, or mute
> the thread
> <https://github.com/notifications/unsubscribe-auth/AAC3n6wncWx60qFnMSNfbYXOPj5c1hzcks5tSzgogaJpZM4RhtUf>
> .
>
|
I think that's orthogonal. The breaking change would be to remove ? as a separator. That would have the benefit of ? being exactly the same as + and *, but...
I tend to agree. The current implementation is not a breaking change. |
text/0000-macro-at-most-once-rep.md
Outdated
|
||
```rust | ||
macro_rules! foo { | ||
($(pat),*,) => { foo!( $(pat),* ) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This rule should be $(pat),+,
so that foo!(,)
is not permitted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 will fix shortly
text/0000-macro-at-most-once-rep.md
Outdated
|
||
```rust | ||
macro_rules! foo { | ||
($(pat),* $(,)?) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds like better support for trailing delimiters is a major part of the motivation for this RFC and why people are excited about it. But the old approach shown under "Currently" still seems better than the one here because with ?
we cannot disallow an invocation consisting of only a comma, foo!(,)
. Is the idea that $(,)?
would be a quick and easy shorthand but macro authors would continue to use the old approach if they want their macro to be maximally correct? If so, could you brainstorm some ideas for how optional trailing delimiters could be better supported?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One way would be a new repetition operator, let's say $(pat),#
(#
obviously up for 🚲 🏡 ), which accepts a delimited list with optional trailing separator, the same way Rust does in most contexts. I think that could be done orthogonally to this RFC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... that's true. It works well if you have + repetition.
One option is to combine ? with | as described in #2298 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another option is to create another repetition mode which indicates trailing commas: $[pat],*
text/0000-macro-at-most-once-rep.md
Outdated
|
||
There are two specific use cases in mind. | ||
|
||
## Macro rules with optional parts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you point out some macros from crates.io that would benefit from this syntax for optional parts? The example given here strikes me as contrived.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have used it in this crate to match the following syntaxes in one rule:
trait Foo { ... }
trait Foo: Bar { ... }
pub trait Foo { ... }
pub trait Foo: Bar { ... }
namely the rule:
($vis:vis trait $traitname:ident $(: $supertrait:ident)? { $($body:tt)* })
(edited to fix local ambiguity)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also strikes me as a candidate for reimplementation: https://docs.rs/clap/2.29.4/clap/macro.clap_app.html
One thing I don't see discussed is that this enables some things to be written with a single rule that used to require extra layers of indirection or even incremental TT munchers. For instance, any example where macro_rules! my_match {
(($expr:expr) {
$( $pat:pat $(if $guard:expr)? => $block:block $(,)? )+
}) => {
match $expr { $( $pat $(if $guard)? => $block )+ }
};
}
fn main() {
my_match!{ (Some(3)) {
Some(n) if n % 2 == 0 => { println!("even"); }
Some(5) => { println!("five"); },
_ => {}
}}
} (Though it still cannot handle all cases unless we had some sort of "alternative operator", like |
The final comment period is now complete. |
That seems like a much more significant addition, though, and it would require bigger changes to the macro parser. |
Implement `?` macro repetition See rust-lang/rfcs#2298 (with disposition merge)
Ok, I added a bit to the drawbacks section to mention @dtolnay's comments in #2298 (review). For now, I think this is still a reasonable step, and we will get more insight by playing around with the preliminary implementation. |
Indeed. I also feel that alternatives carry a cognitive and maintenance burden for macro authors which does not scale well with the size of the problem being solved, and I did not intend to suggest it as a viable alternative. (pun not intended) (in particular, the fact that a macro must ultimately produce an expr, type, or items means that users would be forced to put many orthogonal and/or nested groups of alternatives into a single pattern) |
Musing a bit further, this reasoning could be applied to many proposals for new It seems that, given the unavoidable limitations of That is to say, I think the ability to parse everything is very distinctly a non-goal. |
I disagree. We should make the macro parser Turing complete. (😉 ) |
Oh, it is. But I philosophically disagree on a different level -- more general features create more power than cognitive burden. |
It looks like discussion has died down... |
Perhaps this can be merged now? |
Huzzah! The RFC is merged! Tracking issue: rust-lang/rust#48075 |
Thanks @Centril 🎉 I think rust-lang/rust#48075 is already a tracking issue. |
Request for comments/FCP on newest implementation: rust-lang/rust#51934 |
Rendered
Discussion
EDIT: Implementation in rust-lang/rust#47752
Tracking issue: rust-lang/rust#48075