5 ms·
Rust also has macros, which can easily be defined next to their use: http://doc.rust-lang.org/book/macros.html http://doc.rust-lang.org/book/macros.html Syntax
by mbrubeck 11y ago
Rust also has macros, which can easily be defined next to their use: http://doc.rust-lang.org/book/macros.html http://doc.rust-lang.org/book/macros.html
Syntax extensions are more like plugins for the Rust compiler.
- ajross 11y agoI know, but Rust macros seem to be fairly simple "expansion of a syntax tree" things, not intended as a programming environment. This is (or at least appears to be) the Rust answer for things like elaborate C macros or C++ template metaprogramming. There's a place for that kind of code in the world, even though it's needed rarely. Thinking about this as a "compiler plugin" is exactly what I think I'm getting at: if I need to implement some sort of DSL feature for my code, I want to do it as part of my code and not have to deploy it as a plugin to the compiler.
- mbrubeck 11y agoWell, you can still have your syntax extension live in the same repo as the rest of your code. For example, the Servo repo has a "components/plugins" directory that contains our custom lints and other extensions. And other code in the repo just links to it like this: Cargo.toml: [dependencies.plugins] path = "../plugins" lib.rs: #![plugin(plugins)] This doesn't seem too different from the situation in C where you put your cpp macros in a header file so you can #include them in multiple source files.
- pcwalton 11y ago> This is (or at least appears to be) the Rust answer for things like elaborate C macros or C++ template metaprogramming. Generics are Rust's answer to most template metaprogramming. > if I need to implement some sort of DSL feature for my code, I want to do it as part of my code and not have to deploy it as a plugin to the compiler. The problem with that is that, in a cross-compilation scenario, the environment that the compiler runs in may be completely different from the environment that your code is deployed in. Different symbols may be available, some libraries may or may not be there or work differently, etc. So you really need it to be separate modules.
- ajross 11y agoThat seems kind of non-responsive. The fact that there are technical limitations with Rust's mechanism doesn't invalidate the fact that the existing solutions work fine when implemented with a cross compiler and yours don't. It's sort of a special case of my point: maybe you did it wrong. (Edit, for clarity: the C preprocessor and C++ template languages are well-specified interpreted languages executed at compile time. Rust's attempt here is poorly specified and coupled closely to the runtime environment of the compiler binary. And that choice has leaked into the API presented to the programmer. And that's bad.) And regarding templates/generics: I'm not talking about type calculus stuff, but more like the kind of code you see in Boost's lambda or serialization libraries (which to be fair I think are terrible libraries personally -- IMHO this kind of code doesn't belong in libraries at all, which is my point). I don't think Rust generics (to their credit) can do that.
- pcwalton 11y ago> That seems kind of non-responsive. The fact that there are technical limitations with Rust's mechanism doesn't invalidate the fact that the existing solutions work fine when implemented with a cross compiler and yours don't. It's sort of a special case of my point: maybe you did it wrong. Two of your examples have been template metaprogramming and cpp, both of which are very limited programming environments (technically Turing complete, but both are Turing tarpits). When you actually want a full programming environment, you always hit the cross-compilation issue. It's just fundamental to the problem. But the advantages of a having a full programming environment available, when you need that power, outweigh the downsides of having to write in a separate module. The other example you gave is writing a Python script, which has all the same problems of writing in a separate module, except now you're writing in a different language in addition to writing in a separate module. Sometimes you don't need the power of a real programming environment, of course. That's why the macro system, which does not expose a full programming environment, exists in Rust. But C++ templates and (especially!) cpp weren't designed as programming environments either. They're pretty terrible programming environments. If you want that kind of thing, use the macro system. It's technically Turing complete too in just the same way as templates are. But we also expose a full programming environment, if you want it. I'm mystified by how offering a feature that extends the existing state of the art in addition to offering a feature that reflects the state of the art—the macro system—could possibly be somehow "doing it wrong".
- dbaupp 11y agoRust macros are more powerful than CPP in many ways, e.g. pattern matching and nice variadics. Much easier to write, use and document than either a C macro or C++ templates (although the later is definitely improving in the newest standards). These sorts of macros work very well for large classes of things one would do in with those C/C++, and more beyond that too. Syntax extensions are particularly good at things that not possible without massive hacks in either (although, again, this is somewhat changing with constexpr in C++14 etc). On the point of being inline, yes, it would be helpful sometimes, but often syntax extensions are "standalone": useful functionality that makes sense to be in its own crate (e.g. for publishing to crates.io), especially while they are unstable. And cargo makes it so easy to use other crates (even local ones, even plugins) that it barely matters where it is defined in terms of tooling/infrastructure.