steveklabnik: steveklabnik: “a joke” is a bit much.

I was bored one day, so I wrote something very much akin to Rust’s println! in D. It was just some regular code that got executed at compile time. Completely stable, never broke, should have worked across all D compilers.

By contrast, you can’t even write the formatting part of println! in macro_rules! ; it has to be integrated into the compiler itself because no one sane wants to ship a compiler compiler to the package ecosystem that will break against random compiler versions.

Rust macros are great; they’re not a joke in absolute terms. D is just so much better than Rust at this that comparing them is, frankly, silly. It’s only a joke by comparison.

steveklabnik: steveklabnik: but our stuff can’t generate invalid code, which D’s can if mis-used.

No, that’s not true, either. String mixins are only allowed in specific places in the language grammar, just like macro invocations in Rust. Yes, you can have temporarily invalid constructs in existence during construction of the CTFE result, but the same is true of Rust using push-down macros.

Also, given that the vast majority of complex macros in my experience have to abuse the heck out of tt because Rust doesn’t allow for deconstruction of substituted AST nodes (let alone parsing the language’s grammar), I don’t think the “strongly/weakly typed” metaphor is fair. The moment you go beyond basic matching and substitution, Rust macros turn into “untyped” token munchers.

Ygg01: Ygg01: Wasn’t there a difference, where D templates/macros expand into arbitrary code, like C++ templates do?

I’m talking about CTFE and mixins, not templates. D templates have to be syntactically valid prior to expansion, and semantically valid after. You can’t expand a D template to random gibberish. This is really no different to Rust macros, which behave in more or less the same fashion except that the macro’s body doesn’t have to be syntactically valid in the first place (beyond being a TT).

Ygg01: Ygg01: Why? Aren’t macros just a type of compiler plugins?

Technically yes, but it’s not a useful distinction in this context.

Like I said, CTFE and string mixins are an actual part of D-the-language. Compiler plugins are rustc -specific. They’re extra code that gets linked into the compiler. The only kind of macro that’s stable and part of the language is macro_rules! which isn’t even capable of anything described above.

In general, I never count unstable or implementation-specific features in these comparisons because it’s wildly unfair and borderline deceptive, but I’ve had this flaming row before, and I’m not having it again. I haven’t had nearly enough coffee, and it’d be getting off topic.

Look, I spent years abusing the hell out of D’s metaprogramming abilities. I’ve also spent a lot of my time with Rust doing the same to macros. Rust macros have exactly one advantage over D CTFE+mixins that I can think of: they can leverage the Rust parser. I don’t count being able to execute compiler plugins as a real advantage because those aren’t stable and, as I said, could be done in the D compiler of your choice by modifying the compiler’s source (which would also probably break about as frequently).

Playing up Rust’s macros relative to D is both misleading (at best), and bad for Rust: it gives people who know Rust but not D the impression that they’re not missing anything, that there’s nothing D does better that Rust might learn and improve from.