Braces, square brackets and parentheses in macro-call?


#1

I have encountered three forms of macro call:

macro! {...} 

macro! (...)

macro! [...]

they passed the compiler and did the same thing.
So are they the three identical forms to call a macro ?
If not, could you explain for me ? and which one should I prefer ?


#2

Yes, they are identical. Use whichever you like best. Usually () is for function-like macros, [] is used for vec![…], and {} is for other cases.


#3

thank you :slight_smile:


#4

Ah, i thought one had to use whichever the macro definition uses. Today i learned…


#5

They aren’t quite the same. I’m not sure the exact details, but macros invoked with {} can be used as statements, where as macros invoked with [] or () are always expressions.

See https://is.gd/2jucbe for the difference, for example (there is a syntax error in second).

The relevant RFC is https://github.com/rust-lang/rfcs/blob/master/text/0378-expr-macros.md. I’m not sure if the difference is currently documented anywhere else.


#6

Is it possible to know how the macro got invoked? that is, from within the macro.

In other words, can you write a macro that behaves differently depending on the way it is invoked?


#7

No, the macro doesn’t know if it was called with [] {} or ().


#8

From memory, there’s no difference between [], {}, or (). The compiler will group all tokens inside one the brackets as a single token tree which then gets given to the macro. So by the time the macro gets the token trees, the original type of brackets being used has been erased.

As @tom.prince mentioned, {} are slightly different in that the parser interprets curly braces as a block. So you can have something like error_chain!{} as a top level item, whereas if I used error_chain!() I’d need to put a semicolon at the end to turn it into a valid statement.