Live data from Hacker News

Deriving Traits in Rust with Procedural Macros

naftuli.wtf

21–30 of 31 posts

Re: Deriving Traits in Rust with Procedural Macros

#21
post #20
post #16

Earlier quoted context omitted.

Deriving typeclass implementations is something I do all the time in regular application code (in Scala), once you're used to it it gives you a lot of safety and expressive power. It sounds like Rust would benefit from some kind of record system / generic representation of traits (like we get from Shapeless in Scala) so that generic trait deriving could be written in normal code without needing macros.

Isn't Shapeless based in macros? That said, an equivalent library in Rust would be very useful.

Shapeless has one or two macros in its implementation, but as far as the rest of the ecosystem is concerned it might as well be part of the language. The point is that you can implement a custom typeclass and derivation of instances of that typeclass for struct-like ((possibly recursive) compositions of) sum/product types without ever having to write a custom macro.

Re: Deriving Traits in Rust with Procedural Macros

#22

Rust is morphing into a complexity beast that rivals C++. When the cognitive load require to read and write Rust code far exceeds that required of other, more popular languages, the future does not look rosy.

This may be true, but is not a very constructive comment without pointing out which language features or interactions between language features you find complex. Ownership and the borrows checker may have a steep learning curve, but are not very complex. The rules are quite simple, the learning curve is steep because most programmers do not typically think about ownership (though they should). (In my experience in te…

Presumably the comment is not about Rust ownership rules, but about the language feature on display in the article: procedural macros.

Re: Deriving Traits in Rust with Procedural Macros

#23

Rust is morphing into a complexity beast that rivals C++. When the cognitive load require to read and write Rust code far exceeds that required of other, more popular languages, the future does not look rosy.

Maybe. It has a lot of practical innovations and constraints but some inconsistencies and rough edges that will likely be addressed. Perhaps programming languages need the freedom to try things, make mistakes and then use feedback with an RFC process, which Rust has, to make improvements. Feel free to submit RFCs if you notice anything specific.

RFCs cannot unwind the complexity on display here in this article, unless the Rust community would entertain a proposal for removing procedural macros entirely, which I assume is a non-starter.

Re: Deriving Traits in Rust with Procedural Macros

#24
I'm a little confused about the statement that procedural macros are new in the 2018 edition.

I've always stuck to what Fedora was shiping, and they seem to be shipping the stable versions. Yet I used procedural macros back in 2016 already [0]. Does my memory fail me, or is there some other change that happened now?

[0] https://github.com/rhn/gpx-rust/blob/master/gpx_debug/src/li...

Re: Deriving Traits in Rust with Procedural Macros

#25

Great article, there aren't many resources for writing proc macros right now. However, I think this could be done with a generic impl of WritableTemplate for all T where T: Template.

Yeah, I dropped out after three paragraphs thinking that the author is waaay overdoing it. If this is just a toy example, it should be labeled as such.

Re: Deriving Traits in Rust with Procedural Macros

#26
I'm a Rust fan and procedural macros are legitimately a cool feature, but the example seems much more simply solved via inheritance. You could do this without procedural macros by using a default method definition on the WritableTemplate trait, since WritableTemplate inherits from Template and should have the render method in scope.

This could just be a slightly contrived example to show the neat kinds of things you can do with procedural macros, though. If you needed a reference to the original struct definition, for example, procedural macros allow you to do the kinds of transformations at compile time that other languages need runtime reflection for.

Re: Deriving Traits in Rust with Procedural Macros

#27

Earlier quoted context omitted.

This may be true, but is not a very constructive comment without pointing out which language features or interactions between language features you find complex. Ownership and the borrows checker may have a steep learning curve, but are not very complex. The rules are quite simple, the learning curve is steep because most programmers do not typically think about ownership (though they should). (In my experience in te…

Presumably the comment is not about Rust ownership rules, but about the language feature on display in the article: procedural macros.

The are considerably simpler than the equivalent feature in C++ (template metaprogramming).

Re: Deriving Traits in Rust with Procedural Macros

#28

Great article, there aren't many resources for writing proc macros right now. However, I think this could be done with a generic impl of WritableTemplate for all T where T: Template.

That bugged me, too -- if your entire article is about using a particular tool, then the reason for using that tool should be rock solid.

I found the linked article [1] much more helpful in explaining procedural macros, even though it didn't offer many reasons to use them (other than linking to Serde etc.).

[1] https://blog.rust-lang.org/2018/12/21/Procedural-Macros-in-R...

Re: Deriving Traits in Rust with Procedural Macros

#29

Great article, there aren't many resources for writing proc macros right now. However, I think this could be done with a generic impl of WritableTemplate for all T where T: Template.

Agreed. I was anxiously waiting for proc macros to land on stable for quite a while and was very happy when they did.

But, when the time came to implement my custom derive I had to consult many sources. I ended up piecing together what I needed from a combination of:

  - Official documentation (The Book)
  - Blog posts
  - Reading Serde code (And Syn/Proc-Macro/Proc-Macro2)
I also found the introduction of the proc-macro2 shim crate (however well intentioned) caused quite a bit of confusion. Specifically, it wasn't clean if I should use proc-macro or proc-macro2, and if I should be using the TokenStream exported by the former or the latter. Or should I be using one in some cases, and the other in some cases. Ditto for a few other things that I just can't recall right now.

I did get things put together eventually, but I don't feel I understand things well enough to explain to someone else...yet.

All that said, it's a hugely powerful feature and well worth the time if you need to do things that require intimate knowledge of the AST.

Re: Deriving Traits in Rust with Procedural Macros

#30

Earlier quoted context omitted.

> Borrowing The way I think about this (which isn't quite how rust seems to) is that every value (including references) is always destroyed by passing it to a function, but gets implicitly copied if (arg is copyable && arg is referenced below). Eg: T a = mkT() # create value foo(&a) # create and immediately destroy/pass reference bar(a) # => bar(copy(&a)) # create-and-pass copy baz(a) # last use, so dont bother copyi…

is always destroyed by passing it to a function, but gets implicitly copied if (arg is copyable && arg is referenced below) I am not sure what you are trying to say. This: bar(a) # => bar(copy(&a)) # create-and-pass copy baz(a) # last use, so dont bother copying is not possible in Rust if a 's type is not a copy type. a will be moved when calling bar , so trying to pass it to baz will result in a compiler error. The…

> I am not sure what you are trying to say. [Couple paragraphs rephrasing what I said]

Yep, that's what I was trying to say. (Although I'd hadn't remembered that the Copy trait actually enforced bitwise-exact-copies-only, because why would you want (implicit) non-exact copies.)

Post reply on HN