Why do we call the vec macro using square brackets instead of the parenthesis it is defined with?

Viewed 1799

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?

1 Answers

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 Vecs 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!();
Related