Box::new macro like vec! in Rust

Solution 1:

This is a bit subjective, but vectors are used far more often, I believe. And the vec! macro saves you a lot more code compared to the box! macro you are referring to.

As for the macro implementation, you can write something like this:

macro_rules! bx {
    ($e:expr) => {
        Box::new($e)
    };
}

Here is an example usage:

let b = Box::new(3);
let m = bx!(7);

Note that I named it bx! and not box!, as the latter is a reserved word in Rust.

Solution 2:

however, for some unknown reason Rust guys prefer to use macro for vec! or println!

I suggest asking this the other way around: why couldn't vec! and println! be functions? And the answer is, both are variadic (can take variable number of arguments) and there are no variadic functions in Rust. It's much worse for println!, whose arguments can have different types too; and constraints on those types depend on the first argument! Try writing down a type for println as a function, and you'll find it would be much less usable and less efficient.

The problem vec! solves is smaller. But as Chayim Friedman's comment says, until quite recently you couldn't even have had

Vec::from([1,2,3])

if there were no vec! macro. I think the best you could have done was

Vec::from(&[1,2,3])

As Chayim points out, this is strictly worse than vec!.

Of course, Box::new doesn't have this problem at all. So it's a function just because it didn't have to be a macro.

but as I post the Cons list expample, it's obvious the latter syntax is redundant and does have an issue for readability

In that case box! is no less redundant; instead a way to get rid of redundancy is

fn cons(head: i32, tail: List) -> List {
    List::Cons(head, Box::new(tail))
}

and then

let list = cons(1, cons(2, cons(3, Nil)));

Or even a list! macro and

let list = list![1,2,3];