I've been writing a lot of macros in a recent project. I was just thinking about how incredibly useful Rust's module system is for managing "namespaces", and I began to wonder:
Why was it decided that macros shouldn't also abide by the module system? Is it because of the general rarity of macro use? Or because of some other fundamental compilation process that restricts it?
Is it at all possible to "namespace" Rust macros?
This question doesn't arise from a dire need, but more from a general curiosity :-)
The most widely used form of macros in Rust is declarative macros. These are also sometimes referred to as “macros by example,” “ macro_rules! macros,” or just plain “macros.” At their core, declarative macros allow you to write something similar to a Rust match expression.
A namespace is a logical grouping of declared names. Names are segregated into separate namespaces based on the kind of entity the name refers to. Namespaces allow the occurrence of a name in one namespace to not conflict with the same name in another namespace.
Rust has excellent support for macros. Macros enable you to write code that writes other code, which is known as metaprogramming. Macros provide functionality similar to functions but without the runtime cost. There is some compile-time cost, however, since macros are expanded during compile time.
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.
Macro expansion runs before "the module system", and so name resolution/searching isn't really set up at that point. Also, macros can actually create whole modules, so it's not necessarily possible to have the entire resolution system working. This is also part of the reason that macros are run in declaration order (the only place in Rust where this really matters), so that there's a predictable ordering for names and macros to be defined.
So, there's some technical problems. However it would be really nice to at least have some form of namespaced macros.
It would definitely be possible (and is essentially necessary) to have namespacing between crates, that is, if crates a
and b
both define foo!
, then the following should be able to be made legal
#![feature(phase)]
#[phase(plugin)] extern crate a;
#[phase(plugin)] extern crate b;
fn main() {
a::foo!();
b::foo!();
}
This isn't implemented yet, but we will hopefully have something of this form eventually.
Is it at all possible to "namespace" Rust macros?
In summary: no, except via C-namespacing: mylib_mymodule_mymacro!()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With