4 ms·
Thanks. I am trying to understand where the savings for the user is (as in less code to type). I guess it is somehow related to T being a generic and if they di
by harikb 7y ago
Thanks. I am trying to understand where the savings for the user is (as in less code to type). I guess it is somehow related to T being a generic and if they didn't use this macro, they would have had to repeat this all over?
- aliceryhl 7y agoOne common usage is to use macros to repeat some definition for every integer type. In this case T is not a generic, but the name of the trait.
- estebank 7y agoIn the example given the macro is almost useless. The benefit comes if you want the expanded code to have more things, like methods defined that otherwise you would have your consumer write or sister methods and types. The macros are only about convenience on usage and reduction of boilerplate. A good example is the vec![1,2] macro call that expands to { let mut x = Vec::new(); x.push(1); x.push(2); x } The reason the blog post is using that example is because it's showing a new type of macro argument which accepts items (functions, structs, enums, traits and impls) and expands them correctly without any extra needs by the macro writer.
- cesarb 7y agoJust nitpicking, but a better explanation of the expansion of `vec![1,2]` would use `Vec::with_capacity(2)` instead of `Vec::new()`, that is, it already allocates the Vec with the correct capacity (the real expansion uses in-place construction of a boxed slice, but the effect is similar).
- CDSlice 7y agoIn this specific case the macro isn’t very useful since you can easily write `trait T { ... }` yourself. They tend to be more useful when there is a lot of similar boilerplate code that only differ in a few ways. A macro can cut down most of that repetition. They can also be used to provide pseudo “literals” like the vec! macro does for the Vec data type.
- deleted 7y ago[deleted]
- zamalek 7y agoOne thing I use it for all the time is data-driven tests, e.g. https://github.com/jcdickinson/racemus/blob/master/racemus-binary/src/writer.rs#L476 https://github.com/jcdickinson/racemus/blob/master/racemus-b...
- majewsky 7y agoHere's a real-world example from the code I was working on yesterday: I have several database tables where the records have numeric IDs, and instead of having the ID type be just an int everywhere, I want them to be proper types to avoid mixups. Instead of fn set_document_owner(document_id: i64, user_id: i64) where I could easily provide the arguments in the wrong order, I want fn set_document_owner(document_id: DocumentID, user_id: UserID) where this cannot happen. Each ID type is just a one-element tuple containing an i64, which would just be pub struct DocumentID(pub i64); pub struct UserID(pub i64); //... and so on ... and so on. But in order for them to behave as expected (e.g. with the == operator or when reading/writing IDs in the database), I need to write a bunch of boilerplate. This is the macro that I have now: use rusqlite::types::{FromSql, FromSqlResult, ToSql, ToSqlOutput, ValueRef}; macro_rules! make_id_type { ( $name:ident ) => { ///A type-safe primary key. #[derive(Default, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)] pub struct $name(pub i64); impl fmt::Display for $name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) } } impl ToSql for $name { fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { self.0.to_sql() } } impl FromSql for $name { fn column_result(value: ValueRef) -> FromSqlResult<Self> { Ok($name(i64::column_result(value)?)) } } }; } make_id_type!(DocumentID); make_id_type!(UserID); //... and so on ... This is pretty much the most basic usecase for macros. You can do some more interesting stuff than just take a name and insert it into some template, because macros can actually pattern-match the phrases given to them in the macro invocation. A good example, also from the RDBMS domain, would be https://docs.diesel.rs/diesel/macro.table.html https://docs.diesel.rs/diesel/macro.table.html (link goes to the documentation of the macro).