That does make sense. Well, this still leaves the `foo!!` proposal as viable, and a possible solution for https://github.com/mozilla/rust/issues/9358 - so, +1 for that.
On Thu, Oct 17, 2013 at 9:29 AM, Marvin Löbel <[email protected]>wrote: > As I understand it, there is a high incentive to have macros be > tokenizable and parseable without needing to expand them - it's a > necessarily if we ever want importable macros (Can't resolve macro imports > if you can't parse the source). > Hence the requirement to have explicit brackets and the need to have > properly nested and paired brackets in them. > > > On 10/17/2013 06:30 AM, Oren Ben-Kiki wrote: > > In general I'd favor anything that would help with > https://github.com/mozilla/rust/issues/9358 - that is, allow more > eDSL-ish macros. Writing `foo!!(...) { ... }` has the cost of the extra `!` > but that really isn't too bad. > > That said, I wonder why do macro invocations require the outer set of > parenthesis? Since a macro is expressed in terms of parser rules > (expressions, identifiers, tokens, etc.), isn't it unambiguous to allow > macros to be invoked without the outer `()`? E.g.: > > macro_rules! foo ( > (bar: $expr :<: baz: $expr) => ..., > ) > > Today, one would use it as in `f(foo!(1 :<: 2), 3)`. But suppose one > could somehow indicate the outer `()` were never to be used for this macro > (say writing `syntax_rules!` instead of `macro_rules!`, or by some other > extension of the `macro_rules!` notation), then parsing `f(foo! 1 :<: 2, > 3)` would be unambiguous - assuming we (1) strictly use greedy parsing of > $expr etc. and (2) always expand a later macro before parsing and expanding > earlier macros, where later and earlier are in source text order. This > strategy makes irrelevant the issue of determining the nesting of such > macros while "doing the right thing" with a simple deterministic rule. > > This would probably be more complex to implement than the multiple-`!` > proposal, but would allow for more generic patterns. For example, allowing > to omit the outer `()` would allow invoking `my_match! pattern => action`; > if I understand it correctly, using `!!` would only allow for writing > `my_match!! pattern action`. > > At any rate, this is just as an idea - like I said, I'd like anything > that would allow me to write `foo!(...) { ... }` (or `foo!!(...) { ... }`, > or something along these lines). Writing `foo!(..., { ... })` just seems > ugly to me... > > > On Thu, Oct 17, 2013 at 2:10 AM, Marvin Löbel <[email protected]>wrote: > >> Hello! I was thinking a bit about macros, and I had an idea for a kind of >> syntactic sugar that might be useful to have. I also posted this to the >> issue tracker at https://github.com/mozilla/rust/issues/9894. >> >> # Current situation >> >> Right now, rust knows about two kinds of macro invocation: >> >> IDENT!(...) >> IDENT! IDENT (...) >> >> The latter one is just used by `macro_rules!` right now, and seems kinda >> out of place because of that. >> >> Additionally, just being restricted to `IDENT!(...)` means that, while >> you can define macros just fine, the resulting invocation syntax often >> looks a bit weird because of the need for the outer `()` pair. >> >> For example, if you want to write some kind of custom `match` macro you >> ideally want a syntax like `macro! EXPR { CASES... }`, but in practice are >> forced to decide between redundant, deeply nested brackets or weird syntax >> if you want to reduce the brackets: >> >> ~~~ >> my_match!( >> foo().bar().baz() { >> case 1 => ... >> case 2 => ... >> ... >> } >> ) >> >> my_match!(foo().bar().baz() cases: >> case 1 => ... >> case 2 => ... >> ... >> ) >> ~~~ >> >> # Proposal >> >> We can't just allow macros to accept different syntax like `IDENT! EXPR ( >> ... )`, because it would create ambiguity in the parser, but it occurred to >> me that we _can_ provide syntactic sugar for transforming 'nicer looking' >> variants into the regular `IDENT!(...)` syntax. >> >> Basically, I'm thinking of leveraging the bang in a macro invocation to >> annotate how many following bracket pairs to group into one regular macro >> invocation: >> >> ~~~ >> IDENT!! (...) (...) => desugaring => IDENT!((...) (...)) >> IDENT!!! (...) (...) (...) => desugaring => IDENT!((...) (...) (...)) >> ... etc >> ~~~ >> >> The number of bangs could become confusing fast, but I don't expect that >> macros with more than two bracket groups are going to be common. And >> because it would just be sugar, you could always write it as the regular >> form. >> >> # Advantages >> >> There are a number of advantages I see with this proposal: >> >> 1. The two macro invocation forms can be folded into one: >> ~~~ >> IDENT!(...) => IDENT!(...) >> IDENT! IDENT (...) => IDENT!! (IDENT) (...) == IDENT!((IDENT) (...)) >> ~~~ >> >> 2. Custom syntax can become nicer looking, especially for control >> structures. >> Looking at the `my_match` example: >> ~~~ >> my_match!! (foo().bar().baz()) { >> case 1 => ... >> case 2 => ... >> ... >> } >> ~~~ >> ... which looks more natural than any the two options outlined above. >> >> 3. It's pure syntactic sugar, which means it's easy to implement and >> reason about. >> All `libsyntax` needs to do is to consume a list of bracket-counted >> token trees >> equal to the number of bangs, and introduce an artificial outer >> bracket pair if >> the number is higher than one. >> >> 4. It's just invocation sugar, which means there is no difference between >> defining a >> macro that uses this vs one that doesn't - you just declare them all >> assuming the >> explicit outer `()` pair. >> >> # Potential issues >> >> The possible issues I can see with this are confusing error messages if >> the number of bangs is wrong, and uncertainty about which brackets belong >> to a macro invocation and which are regular rust code if their contents >> become big and/or their number become high. >> >> However, in theory rust might be able to provide good error messages for >> the first one, because if the macro name is right you'd get an `No rules >> expected this ...` error, and there could be some heuristics for >> recognizing cases where the user has do add/remove bangs to match the macro >> definition. >> >> And the second one can likely be managed by syntax highlighting, and by >> the usual convention of not abusing the syntax to the point where it >> becomes illegible. >> >> # Backwards compatibility >> >> Adding this sugar would be backwards compatible because it doesn't change >> any existing macro syntax, however if `IDENT! IDENT (...)` ends up obsolete >> through this, that would break existing uses of `macro_rules!` - but macros >> are behind a feature flag anyway at this point, so it wouldn't matter as >> much. >> >> _______________________________________________ >> Rust-dev mailing list >> [email protected] >> https://mail.mozilla.org/listinfo/rust-dev >> > > >
_______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
