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 <loebel.mar...@gmail.com>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<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
> Rust-dev@mozilla.org
> https://mail.mozilla.org/**listinfo/rust-dev<https://mail.mozilla.org/listinfo/rust-dev>
>
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to