1) It has already been pointed out, that macro foo { /* pattern */ } { /* substitute */ } would have serious parsing issues. What if the pattern looks like a macro definition ($bar: ident) => { $bar }, or almost looks like a macro definition like ($bar: ident) => { $baz: ident }. And what if the substitute-block could just be interpreted as a normal block inside a function body? This is not only an algorithmic problem to the compiler, but also about readability by human beings.
To disambiguate this I feel like the shorthand notation for macros with only one matcher should always be with parentheses
- shorthand:
macro foo ( /* pattern */ ) { /* substitute */ }
- vs. general:
macro foo { /* 1-n matchers */ }
I think this limitation improves readability (and parsability) a lot. This means braces and brackets around the matchers could only be used in the general form. I think the readability improvement is worth of this tradeoff. Of course, you could also allow the bracket-style shorthand macro foo [ /* pattern / ] { /* substitute */ }.
2) Another question is, whether the delimiters (), [], {} should be part of the matcher or not, i.e. must the delimiters of the macro usage match with its pattern declaration and should it be possible that foo!() and foo![] expand differently, because the delimiters are part of the matcher?? I am not sure about this.
Currently it has no meaning and the caller can use whatever delimiter (), [], {} he likes, independent of the declaration.
My personal taste would be to let the caller decide which calling syntax he/she prefers and to restrict the delimiters for macro declaration to (..):
-
foo!{..} is just an equivalent to foo!(..); or {foo!(..)} independently of the macro declaration
-
foo!(..) and foo![..] are equivalent independently of the macro declaration
- any macro pattern matcher (at the macro declaration) must always be delimited with parentheses
(..), but never with braces {..}
Alternatively we could drop (2.) and allow bracket-delimited matchers [..] in (3.). In this case foo!{..} would be equivalent to {foo!(..)} but not to {foo![..]}.
My key point is that the ‘calling’-syntax foo!{..} does something differently at use-site, i.e. independent of the declaration of foo. At least this is my current tendency.