Rust 中的宏和函数有什么区别?

What is the difference between macros and functions in Rust?

转自Rust blog:

One last thing to mention: Rust’s macros are significantly different from C macros, if you’ve used those

Rust 中的宏和函数有什么区别?它与 C 有何不同?

继续阅读文档,特别是 the chapter on macros!

Rust 函数与 Rust 宏

宏在编译时执行。它们通常扩展为编译器需要进一步处理的新代码。

Rust 宏与 C 宏

对我来说最大的不同是Rust macros are hygenic。书中有一个例子解释了卫生会阻止什么,还说:

Each macro expansion happens in a distinct ‘syntax context’, and each variable is tagged with the syntax context where it was introduced.

它使用这个例子:

For example, this C program prints 13 instead of the expected 25.

#define FIVE_TIMES(x) 5 * x

int main() {
    printf("%d\n", FIVE_TIMES(2 + 3));
    return 0;
}

除此之外,Rust 宏

  • 可以与编译后的代码一起分发
  • 可以在参数计数中重载
  • 可以匹配大括号、圆括号或逗号等语法模式
  • 可能需要重复输入模式
  • 可以递归
  • 在语法级别操作,而不是文本级别

macro中,您可以采用可变数量的参数。

function中你必须定义参数的数量和类型。

引用自the Rust documentation

The Difference Between Macros and Functions

Fundamentally, macros are a way of writing code that writes other code, which is known as metaprogramming. In Appendix C, we discuss the derive attribute, which generates an implementation of various traits for you. We’ve also used the println! and vec! macros throughout the book. All of these macros expand to produce more code than the code you’ve written manually.

Metaprogramming is useful for reducing the amount of code you have to write and maintain, which is also one of the roles of functions. However, macros have some additional powers that functions don’t.

A function signature must declare the number and type of parameters the function has. Macros, on the other hand, can take a variable number of parameters: we can call println!("hello") with one argument or println!("hello {}", name) with two arguments. Also, macros are expanded before the compiler interprets the meaning of the code, so a macro can, for example, implement a trait on a given type. A function can’t, because it gets called at runtime and a trait needs to be implemented at compile time.

The downside to implementing a macro instead of a function is that macro definitions are more complex than function definitions because you’re writing Rust code that writes Rust code. Due to this indirection, macro definitions are generally more difficult to read, understand, and maintain than function definitions.

Another important difference between macros and functions is that you must define macros or bring them into scope before you call them in a file, as opposed to functions you can define anywhere and call anywhere.