As someone who has spent a _lot_ of time writing declarative and procedural macros, the important thing to ask before digging into a macro is whether you need a procedural macro at all.
Complex proc macros absolutely do slow builds down. In many cases, a proc macro only need to be a stub that can delegate to a declarative macro.
You may not need to use syn/quote, but if you are doing any sort of processing/parsing of Rust code you pretty much need to.
FWIW, I really hope that the Rust project focused on finer-grained token matching in declarative macros so we can migrate most proc_macro code away. The macro system is powerful, but nowhere near where it needs to be.
gwerbin 1 days ago [-]
It's interesting seeing this discussion in Rust because it's the same discussion that's been happening around macros in Scheme for decades. It's one of those things where there probably is no universal correct answer, so might as well allow both in your language and let the programmer decide what's best for their case.
teleforce 17 hours ago [-]
I think D got it right by not supporting any macro, and become very fast in compilation while being consistent in the syntax, easier to maintain and debug. This remind me of a famous quote, "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."
D also show the programming world that you don't need to go macro, or Ruby styled 'macro' that can create complicated franskeintein codes in order to achieve good metaprogramming capability [1].
[1] Metaprogramming is less fun in D (88 comments):
My rule of thumb has always been that, macros are great for general things but very bad for domain-specific things.
A macro like (logged-fn) that defines a function which logs the arguments passed, is wonderful.
But if you see a macro like (validate-report), something very wrong happened.
afdbcreid 17 hours ago [-]
As someone that works on rust-analyzer, complex proc macros do slow down things but complex macro_rules much more. And they're also much more complicated to understand.
If you can skip `syn` or `quote` by this, for sure do it (although they probably will be included anyway by other crates). But if not, it's not worth a lot.
mamcx 24 hours ago [-]
yeah, lets be clear:
Most of the proc macros non-sense is to be able to annotate the enum or struct without wrapping it.
P.D: Is there a true actually reason for proc-macros apart for this weird restriction?? And even if yes, how much nice things will be if this kind of scenario was already present so most not need to reach for proc-macros
mmastrac 22 hours ago [-]
Types and generics are hard to parse in regular macros without a tt muncher. Ditto for fn args. If you need to do actual matching of types, you can't capture them as $xxx:ty because Rust will not allow a larger matched token to be broken up again (unless you use a paste! hack to roundtrip it back into ungrouped tokens).
That's really cool, I was not familiar with this and will look into it!
Sagi21805 1 days ago [-]
Yea that's sound about right
The macro explained in that section was mainly for me to learn macros, and save up some boilerplate with nice syntax.
mmastrac 1 days ago [-]
Great writeup! Apologies if it came across as a criticism of the writeup itself, more of a frustration of years in the proc_macro space.
It's surprising how little information exists out there about proc_macros in general.
Sagi21805 1 days ago [-]
Thanks!
Couldn't agree more, both on proc macros and operating system, I did not find sufficient information on the internet. That is exactly the purpose of this book.
1 days ago [-]
Sagi21805 7 days ago [-]
During the development of Learnix operating system I needed to represent bitflags inside some structures.
While there were alternatives with 3rd party libraries, the goal of the project is to implement and learn as much as I can.
Most of the guides I found online explained the concept great, but created only a simple macro as an example. So I decided to write about it myself too, with a real usage to create a bitfields attribute proc-macro, that takes a struct and turns it into bitfields.
Hope you will have a great read!
an_d_rew 1 days ago [-]
Very nice writeup, thank you for the time and effort!
Sagi21805 1 days ago [-]
Thanks for the warming comment!
bigstrat2003 24 hours ago [-]
I'm really confused by the unwrap_or_break example in this text. The article says it wouldn't be possible to do without a macro, but how is it not equivalent to
for d: Option<i32> in data {
let val: i32 = match d {
Some(v) => v,
None => break
};
// Other stuff
}
As far as I can tell that would do the exact same thing as the macro example.
gwerbin 23 hours ago [-]
It said you can't do it with a regular function, not that you couldn't do it any other way.
Sagi21805 23 hours ago [-]
Said the inner block inside the for loop could not be a function, because break does not mean anything not inside a loop, but the macro, which seems like a function, injects it into the code which is inside a loop, which is valid
swordlucky666 1 days ago [-]
[dead]
Rendered at 18:00:10 GMT+0000 (Coordinated Universal Time) with Vercel.
Complex proc macros absolutely do slow builds down. In many cases, a proc macro only need to be a stub that can delegate to a declarative macro.
You may not need to use syn/quote, but if you are doing any sort of processing/parsing of Rust code you pretty much need to.
FWIW, I really hope that the Rust project focused on finer-grained token matching in declarative macros so we can migrate most proc_macro code away. The macro system is powerful, but nowhere near where it needs to be.
D also show the programming world that you don't need to go macro, or Ruby styled 'macro' that can create complicated franskeintein codes in order to achieve good metaprogramming capability [1].
[1] Metaprogramming is less fun in D (88 comments):
https://news.ycombinator.com/item?id=14165198
A macro like (logged-fn) that defines a function which logs the arguments passed, is wonderful.
But if you see a macro like (validate-report), something very wrong happened.
If you can skip `syn` or `quote` by this, for sure do it (although they probably will be included anyway by other crates). But if not, it's not worth a lot.
Most of the proc macros non-sense is to be able to annotate the enum or struct without wrapping it.
So that is why I use this hack:
https://docs.rs/macro_rules_attribute/0.2.2/macro_rules_attr...
P.D: Is there a true actually reason for proc-macros apart for this weird restriction?? And even if yes, how much nice things will be if this kind of scenario was already present so most not need to reach for proc-macros
I wrote https://crates.io/crates/type-mapper as a way to work around those limitations but it is _very_ painful TBH.
The macro explained in that section was mainly for me to learn macros, and save up some boilerplate with nice syntax.
It's surprising how little information exists out there about proc_macros in general.
Couldn't agree more, both on proc macros and operating system, I did not find sufficient information on the internet. That is exactly the purpose of this book.
While there were alternatives with 3rd party libraries, the goal of the project is to implement and learn as much as I can.
Most of the guides I found online explained the concept great, but created only a simple macro as an example. So I decided to write about it myself too, with a real usage to create a bitfields attribute proc-macro, that takes a struct and turns it into bitfields.
Hope you will have a great read!