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

Reply via email to