For a solution to Exercism's Space Age exercise.
I stayed well clear of writing custom macros for a long time. They seemed awesome, but they must be really complicated, I thought. After all, they're more powerful than macro_rules! macros and those look like confusing.
Well, I finally tried it and it wasn't nearly as bad as I thought it would be. Several times I crossed my finger and ran cargo build
to find... no errors, it just worked? So I'm very chuffed and thought I'd share the news.
The space-age-derive crate is on github.
I managed to run into and then avoid one pitfall. I needed an attribute to implement this trait, to fill in an associated constant. So I wanted to do basically
#[my_constant = 12]
struct Foo
and have that impl the trait for me. I did this using a bare attribute macro (which you can see in the history on github if you're curious). But to get it to work it needed a couple of janky things. One, to use crate::MyTrait
to reference the trait I was implementing. So it only worked since the trait was defined in the crate consuming my macro. Otherwise it would complain about missing imports. The other thing was it returned both the struct and the trait impl which seemed wrong.
Then I realised/remembered that derive macro helper attributes were a thing i.e. #[proc_macro_derive(MyTrait, attributes(my_helper_attr))]
and now it's a proper derive macro, much cleaner!
Also, the Syn and Quote crates are fantastic! They can be intimidating at first, but it's worth diving in, referring to examples and reading the docs for what you need to use - I don't think I could read through the whole Syn docs, it's a big crate
There's lots about proc macros I don't understand yet, and my derive is very simple, but I did it and feel like I can add custom derives to my toolbox - yay!