Box::new 像vec这样的宏!在生锈

Box::new macro like vec! in Rust

我在 Rust 语言中看到了很多 Box::new 的用法。

https://doc.rust-lang.org/book/ch15-01-box.html

fn main() {
    let b = Box::new(5);
    println!("b = {}", b);
}

但是,我认为这有点多余,尤其是在这样的代码中:

enum List {
    Cons(i32, Box<List>),
    Nil,
}

use crate::List::{Cons, Nil};

fn main() {
    let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
}

现在,我想使用宏以简洁的方式编写,正如我们所见 vec!

https://doc.rust-lang.org/book/ch19-06-macros.html?highlight=vec#declarative-macros-with-macro_rules-for-general-metaprogramming

let v: Vec<u32> = vec![1, 2, 3];

所以使用 box! 宏,我们可以写:

fn main() {
    let b = box!(5);
    println!("b = {}", b);
}

fn main() {
    let list = Cons(1, box!(Cons(2, box!(Cons(3, box!(Nil))))));
}

我的问题是

  1. box!宏为什么不流行 在 Rust 中经常使用?

  2. 定义宏的正确方法是什么?有什么注意事项吗?

这有点主观,但我相信矢量的使用频率要高得多。与您所指的 box! 宏相比,vec! 宏为您节省了很多代码。

至于宏的实现,可以这样写:

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

这是一个用法示例:

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

请注意,我将其命名为 bx! 而不是 box!,因为后者是 Rust 中的保留字。

感谢@at54321,我用谷歌搜索并找到了

https://doc.rust-lang.org/beta/unstable-book/language-features/box-syntax.html

#![feature(box_syntax)]

fn main() {
    let b = box 5;
}

所以,已经存在了。

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

我建议反过来问:为什么 vec!println! 不能是函数?答案是,两者都是可变的(可以接受可变数量的参数)并且 Rust 中没有可变参数函数。 println! 的情况更糟,它的参数也可以有不同的类型;这些类型的约束取决于第一个参数!试着写下 println 的类型作为一个函数,你会发现它的可用性会大大降低 并且 效率也会降低。

vec!解决的问题比较小。但正如 Chayim Friedman 的评论所说,直到最近,你甚至还没有

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

如果没有 vec! 宏。 我认为你能做的最好的是

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

正如 Chayim 指出的那样,这比 vec!.

更糟糕

当然,Box::new完全没有这个问题。所以它是一个函数只是因为它没有是一个宏。

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

在那种情况下,box!同样是多余的;相反,摆脱冗余的一种方法是

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

然后

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

甚至 list! 宏和

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