Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define some macros as 'private' to a module, when using `macro_use` in Rust?

I have a file which contains shared macros for a Rust project.

Since I want to re-use the macros across the crate (between modules), I declare the module with #[macro_use].

While writing the macros, I split out some shared logic into a macro to avoid repetition, in this case I can't use a private function, it needs to be a macro. If possible, I'd like to hide this shared macro so it can't be used directly by other modules.

Is there a way to make some macros private, so they aren't exposed to other modules in the same crate via #[macro_use]?

like image 487
ideasman42 Avatar asked Nov 08 '16 07:11

ideasman42


People also ask

Can you use macros on Rust?

The most widely used form of macros in Rust is the declarative macro. 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.

How do I export macros in Rust?

macro_rules! macros can be exported from the current crate using #[macro_export] .

What is macro_rules?

macro_rules allows users to define syntax extension in a declarative way. We call such extensions "macros by example" or simply "macros". Each macro by example has a name, and one or more rules.

How do macros work in Rust?

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.


1 Answers

There actually is an idiom in Rust, to hide away "implementation-detail" macros.

Rather than declaring a separate macros, you can instead declare a separate case within the existing macro. The examples I've seen would use the impl keyword for this, and the impl cases are located at the bottom of the macro definition.

Thus, instead of:

macro_rules! hello_impl {
    ($name:expr) => {
        println!("Hello {}!", $name);
    }
}

macro_rules! hello_world {
    () => {
        hello_impl!("world");
    }
}

You use:

macro_rules! hello_world {
    () => {
        hello_world!(impl "world");
    },
    (impl $name:expr) => {
        println!("Hello {}!", $name);
    }
}

This way, there is no implementation macro any longer; and you only have one macro to export.

like image 183
Matthieu M. Avatar answered Oct 19 '22 23:10

Matthieu M.