Twitter | Search | |
Martijn Faassen
Programming frameworks often define declarative domain specific languages. A web framework for instance can have a declaration for a URL route. A command-line tool framework can have a declaration for defining a tool and its argument. How can this be done in Rust? 1/n
Reply Retweet Like More
Martijn Faassen Nov 23
Replying to @faassen
I have some experience with building such frameworks with Python. But how do you do this in Rust? I don't know as I'm a Rust noob and I'm just exploring it in these tweets. 2/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
I know Rust *can* do this. But it doesn't have the import-time side effects of interpreted languages like Python and JS. You can't just register something in a registry when you import stuff. 3/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
This lack of side-effects is a restriction of Rust, which leads to various useful properties that make sense in a systems programming language. 4/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
But Rust does have macros and they can be very powerful. I don't know much about Rust macros yet. 5/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
Digging around I found a Rust web framework called Rocket that lets you write code like this: 6/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
This #[post("/user", data = "<new_user>")] business is what interests me. It also takes information from the function declaration itself, which I've done in Python too. It looks a lot like a decorator in Python. How is it implemented? 7/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
The #[...] bit is a Rust attribute. You can place them in front of functions and structs and such. It's like #[derive], which I've used many times, even as a Rust noob. 8/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
The language feature in play here is procedural macros. 9/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
The Rocket bit looks like a particular type of procedural macro called an attribute-like macro. 10/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
Macros run at compile time, so live in a different world. They get their contents as token streams. This is how far I got so far. It's going to take some time to comprehend how to use this. 11/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
I looked at Rocket's implementation of its route macro. At first I was intimidated by the amount of code! 12/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
I looked at it for a bit longer. Much of the code involves route parsing, which is less intimidating. The rest involves code generation. I *think* some of the macro code generates registrations for the routes, but I'm still digging around. Scary to this noob 13/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
I think I see code to check for duplicate route registrations. So the innards of Rocket do things a configuration framework like my Dectate (in Python) do, but in a more ad-hoc manner. 14/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
Is there a Rust crate already that makes it more general? A framework for building attribute-style procedural macros? A framework-building framework? 15/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
Things I'm looking for in such a framework-building framework include conflict detection, dependencies between configurations (one after another), overrides, multiple configuration "namespaces", etc. 16/n
Reply Retweet Like
Martijn Faassen Nov 23
Replying to @faassen
If it doesn't exist yet, and if it seems useful, I'm not yet the Rust developer who can build it. I'm still struggling with lifetimes and I'm not yet ready to dive into code generating macros. But I might still play with this stuff a little bit sometime... 17/17
Reply Retweet Like