How to use a vector of `TokenStreams` (created with `quote!`) within `quote!`?

I am trying to create a procedural derive macro that creates methods for each field of a struct. I understand how I can create a constant number of methods within an invocation of my macro, but I am at loss when trying to create a Vec<TokenStream> and then concatenating that somehow.

For example, I have something like this:

// create some functions dynamically for each field
let functions: Vec<_> = fields.iter().map(|field| {
    quote!{
        fn #field(&mut self) -> String {
            // ...
        }
    }
}).collect();

let generated_code = quote!{
      impl Struct {
            #functions
      }
};

Is there any good way to do this?

The two simplest ways would be quoting the repetition:

    let generated_code = quote! {
          impl Struct {
                #(#functions)*
          }
    };

or leaving the quoting unchanged and collecting directly into a single TokenStream instead:

let functions: TokenStream = fields.iter().map(…).collect();

Playground

1 Like

Nice thanks, I didn't know that was possible!

The first solution is basically the first thing in the documentation of quote!, and the second one can be inferred from the docs of TokenStream. (It is also analogous with std's behavior in how string-like types can be collected into a single String.)

1 Like

Thanks for bringing that into simple terms for me!