One of the advantages of using macros is that they don't evaluate their arguments eagerly like functions do, which is one of the motivations to use macros other than functions.
By eager evaluation, we mean that a function call like foo(bar(2)) will first evaluate bar(2) and then pass its value to foo. Contrary to that, this is a lazy evaluation, which is what you see in iterators.
A general rule of thumb is that macros can be used in situations where functions fail to provide the desired solution, where you have code that is quite repetitive, or in cases where you need to inspect the structure of your types and generate code at compile time. Taking examples from real use cases, Rust macros are used in a lot of cases, such as the following:
- Augmenting the language syntax by creating custom Domain-Specific Languages (DSLs)
- Writing compile...