I am learning Rust macros and am confused about the syntax while using vec
. The source code implementing vec!
:
macro_rules! vec {
($elem:expr; $n:expr) => (
$crate::vec::from_elem($elem, $n)
);
($($x:expr),*) => (
<[_]>::into_vec(box [$($x),*])
);
($($x:expr,)*) => (vec![$($x),*])
}
Let's forget the standard way to use it:
let v0 = vec![1, 2, 3];
If we look at the source code, shouldn't we use it like below?
let v1 = vec!(3; 1);
let v2 = vec!(1, 2, 3);
Why do we use []
instead of ()
in v1
and v2
compared to v0
?
What Does Bracket Mean? Brackets, or braces, are a syntactic construct in many programming languages. They take the forms of "[]", "()", "{}" or "<>." They are typically used to denote programming language constructs such as blocks, function calls or array subscripts.
We use a dollar sign ( $ ) to declare a variable in the macro system that will contain the Rust code matching the pattern. The dollar sign makes it clear this is a macro variable as opposed to a regular Rust variable.
Rust has excellent support for macros. Macros enable you to write code that writes other code, which is known as metaprogramming. Macros provide functionality similar to functions but without the runtime cost. There is some compile-time cost, however, since macros are expanded during compile time.
Derive macros These macros can create new items given the token stream of a struct, enum, or union. They can also define derive macro helper attributes. Custom derive macros are defined by a public function with the proc_macro_derive attribute and a signature of (TokenStream) -> TokenStream .
As you note, you can use parenthesis, square brackets, or curly braces to call a macro:
let a = vec!(0, 1, 2);
let b = vec![0, 1, 2];
let c = vec! { 0, 1, 2 };
Macros don't care about which of these syntaxes you use1. Programmers care about which syntax you use.
Rust's array and slicing syntax uses square brackets and Vec
s are highly related to both of these. Using square brackets for constructing a Vec
is simply the language convention. Rustfmt will automatically convert calls to vec!
into square brackets.
1 - There's a small interaction between which brace style you use when invoking a macro and semicolons. A macro used as an item or statement is required to end with a semicolon if it doesn't use curly braces:
macro_rules! dummy {
() => {};
}
// Not OK
dummy!()
// OK
dummy! {}
// OK
dummy!();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With