The Little Book of Rust Macros

Yeah, my bad. It works fine without errors. I must have just been on the wrong commit or something like that.

Interestingly, the minutiae/hygiene page shows light themed code on dark themed content but it only seems to be that way because the code was written as custom html.

How easy was it to convert? That could give us an idea how easy it would be to convert rust book :smile:

Super simple. This will probably work but I didn't test this script out. This assumes your distro automatically sees files inside ~/bin as on the path which ubuntu seems to do.

cd ~/Programs
git clone https://github.com/azerupi/mdBook.git && cd mdBook
sudo npm install -g stylus nib
cargo build --release --features="regenerate-css"

cd ~/bin && ln -s ~/Programs/mdBook/target/release/mdbook
cd ~/Programs && git clone https://github.com/DanielKeep/tlborm.git

cd tlborm && rm -r static build.py && mv text src

# Swap `%` to `#` on the first occurence of the first line for all files found
# inside directory `src`
find src -type f -print0 | xargs -0 sed -i '1s/%/#/'

mdbook build

firefox book/index.html

[EDIT]

Added the sed part

I thought there would be at least some tweaking needed, but it seems not. Amazing! :smiley:

Nice read. It could probably save me a lot of time when writing few complex macros.

I can't find if you mention that "/// comment" is just a syntax sugar for #[doc=" comment"]. This may probably be useful in "Enum parsing" section (originally I used to think that the comments are not language items).

Actually, if the "Building Blocks" chapter gets significantly larger, I'll be tempted to have a matching cargo crate so that they're all immediately usable

I'm thinking of some building block for parsing enums and structs. So that serialization libraries, visitors and other useful tools do not need syntax extensions. Think of macro version of "#[derive(..)]". But I'm not sure how this thing could look like in generic way.

Is there a big, complicated macro that you'd like to see explained

Probably quick-error is a good candidate

Wasn't this going to be published by someone? If so, when do you think that will be available, I like to support Authors and their work, so would rather purchase it than rip it into a epub for my Kindle :smile:

Awesome. I don't have the time right now to optimize the formatting to look good in PDF/EPUB, but here is a preview of the current version: Add The Little Book of Rust Macros (WIP) by killercup Ā· Pull Request #25 Ā· killercup/trpl-ebook Ā· GitHub

1 Like

This is fantastic! Thank you!

Great book! ... but dark background makes it difficult to read. :innocent:

Rust theme looks fine )

Credits go to @mdinger for the rust theme (and basically all the others) :wink:

I vote we just change rustbook to accept # on the first line as well. I never did understand why it demands %. Then, we might be able to use the two interchangeably.

I don't think I do. Opened an issue.

I'm sure I don't know what you're talking about.

Hey, it's your macro; who better to explain it? I actually had a second annotated example I was working on just prior to starting this topic, but I decided the macro itself wasn't "best practices". Well, that and it did one or two questionable things.

I was annotating error_type and... hey, waitaminute...

Not that I'm aware of.

I'm beginning to think this clearly deviant attitude is just a function of people on Discourse. All the peeps on IRC loved it. You just need to reconnect with your inner terminal user.

2 Likes

Maybe I want to read Rust Macros like a poem, on evening, with cup of tea, near a fire-place after the full day of chatting... and keep hardcopy on the shelf.

Adjustable background will be a better solution :grinning:

1 Like

Hey, it's your macro; who better to explain it? I actually had a second annotated example I was working on just prior to starting this topic, but I decided the macro itself wasn't "best practices".

Well, I'm not sure mine have best practices too (at least I use bare upper case keywords instead of @xxx for internal rules). And I'm not sure I'm a good enough writer :slight_smile:

Think of macro version of "#[derive(..)]".
I'm sure I don't know what you're talking about.

Well, this is great start. But when writing quick error I quickly found that the most complex thing is to parse the structure itself. Which is explicitly not a job of a macro as described in documentation:

It is the derivation macro's job to parse the item correctly.

I think it might be easier for structs (i.e. my biggest problem was variations of enums, and I even did not try to parse struct enums). And it would be nice if every field could be provided some annotation, like in golang, or like in quick-error. This could allow a more flexible "std::default" implementation for example.

Thank you for $(,)*! This and the advice about putting more specific rules first should probably be in the TRPL.


This seems to me no less confusing than the keyword-identifier duality. expr must be followed by , or ; for some value of "followed":

macro_rules! recurrence {
    ( a[n]: $sty:ty = $($inits:expr),+ ... $recur:expr ) => {
//                                     ^~~ changed
        /* ... */ ()
    };
}

fn main() {
    let fib = recurrence![a[n]: u64 = 0, 1 ... a[n-1] + a[n-2]];
//                                         ^~~ changed

    for e in fib.take(10) { println!("{}", e) }
}

There's also newtype_derive, enum_derive, and one macro in conv. I also have a partial stable macro implementation of serde's... I think it's the encoding trait. Partial mostly because Serde is a pain to generate serialisation code for. I find it's actually easier to parse structs and enums in macros, weirdly.

There are, however, problems with having this parsing as general building blocks:

  1. Because there's no good way to pass around complex data structures that are themselves easy to parse, you pretty much need to tie the parsing logic to the logic that uses the information being parsed. Which means you pretty much need to write the parser from scratch every time for your specific needs. Simplistic things like parse_unitary_variants! aside.

  2. There is no way to match lifetimes, which means you can't ever do a truly complete parse. This is a problem with something like derivation macros, because you generally need to parse generic parameters so that you can establish trait bounds. Lifetimes just completely break this.

  3. When I posted about this last time, the response was basically "meh". Since then, there've been maybe one or two people that seemed interested in the ideas. Between that and the limitations above, I'm not terribly motivated to develop the related code any more than I absolutely have to.

Haha. Yeah. Weird, huh? It's almost like there's a bug in the macro parser that allows non-following tokens after a capture if the capture's inside a loop, and that fixing this would require the entire chapter to be nuked from orbit and rewritten from scratch since obviously there's no nice way of writing the macro without devolving to a TT muncher, and that'd be a horrible introduction. Almost like I'd maybe kinda managed to forget about that and just ported an old article over to the book without thinking about it too much.

But I'm sure there's a less "stop breaking my macro articles plz" explanation. Must be. *sobs*

So @DanielKeep is a Caravan Palace fan! Good to know! :wink:

1 Like

You might say Iā€¦

( ā€¢_ā€¢)>āŒā– -ā– 
(āŒā– _ā– )

ā€¦identify as one.

1 Like