Rust macros in few sentences
So, you've been writing Rust for a few days or so; or even a few weeks or months, or years, or decades. But! you've heard macros and have been burning to know what it's all about.
Claimers and disclaimers
What this article is about
It just explains what macros are in Rust with a few references
What this article is not about
It does not:
- Teach you how to create macros or how to use them
- Lead you to a blissful world of Rust including the use of macros
- Contain expressive code examples of macros
Let's go
Macros are simply a feature of Rust (if not the most powerful) that allows you to write code that writes other code. I'll show you what I mean:
So, let's say I wanted to write a code that ensure that when invoked on an expression or assignment or statement, would print "Hello world" before the operation is carried out; I can write a special function that would insert the line for "Hello world" in a safe place within that expression, assignment or statement. Code example in pseudocode (why? because it will take long for me to explain the actual code in Rust and I'm sure you read the Disclaimer section):
# define a macro
macro_rules hello_world (thing: expression, assignment or statement) -> Valid_Code {
var final_code = Valid_Code();
final_code.append('print("Hello, World!")');
final_code.append(thing);
return final_code.to_valid_code();
}
Then I can use my macro like so:
hello_world!(
add(4, 8)
)
and it will print "Hello, World!" before executing the code.
You get the concept?
Now if you've got pretty good eye, you'll say "That exclamation mark after hello_world
is familiar, cos I've used it to pipe content to stdout using println!
". Yeah, that's because println!
is a macro...
But then...
Actually, there are two types of macros you'll see:
Declarative macros
This macro tends to match against patterns and replace the code you've dropped with other code. An example of this macro is the vec!
macro.
Procedural macros
These macros (there are three types of them) are more magical and tend to accept some code as an input, operate on that code, and produce some code as an output (as quoted from the Rust book). They are the ones you impose on structs like #[derive()]
or the #[tokio::main]
we use when using the Actix framework.
Hoping your imaginations are as wild as Abraham the Mage in The Secrets of the Immortal (very nice book I'm reading), you'll begin to see limitless ways macros can be used.
You can literally add any feature to structs, add methods to structs, attributes and so on.
You can make work easier for people when using piece of functionality like they did when Graydon's boys gave we Rustaceans vector = vec![1, 2, 3, 4]
to use instead of:
let vector = Vec::new();
vector.push(1);
vector.push(2);
vector.push(3);
vector.push(4);
Where else can I see macros?
They are everywhere. From that #[derive()]
syntax you see to the println!
you tend to use instead of an actual debugger. The Rust Book talks more extensively about macros and you'll learn to use them more and creating them by reading that book.
You can also read The Little Book of Rust Macros to shit yourself on macros.
Thank you
Do this by liking and sharing this article with your handsome and beautiful friends.
Best in inclusion
Yeah, I know the "bold of me to assume people define friends with articles such as 'handsome' and 'beautiful'". I was hoping to use a compliment_someone!
macro there, but you'll need to read the link I put up there to understand it.
San kyo :fire
Subscribe to my newsletter
Read articles from Adeoti Ayodeji directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Adeoti Ayodeji
Adeoti Ayodeji
Software engineer, attracted to complex things by nature; passionate about Rust.