dtolnay / quote

Rust quasi-quoting
Apache License 2.0
1.32k stars 90 forks source link

Feature: allow interpolation of any block that returns ToTokens #275

Closed Pistonight closed 4 months ago

Pistonight commented 4 months ago

Currently there is support for interpolating iterators but it often requires constructing the iterator in one place and using it in another

For example, deriving something from the enum variants:

let mut idents = Vec::new();
let mut exprs = Vec::new();
for ident in &my_enum.variants {
  idents.push(ident.clone());
  exprs.push(quote! { /* something */ })
}

// ... later
quote! {
   // ... some other stuff
  match x {
    #(  #idents => #exprs,  )*
  }
  // ... some other stuff
}

For large macros, it creates a lot of temporaries to be used later. Also personally, I found it easier to build and work with TokenStreams directly rather than levels of iterators in quote

let mut match_arms = TokenStream::new();
for ident in &my_enum.variants {
  match_arms.extend(quote! { #ident =>/* something */, });
}

// ... later
quote! {
   // ... some other stuff
  match x {
    #match_arms
  }
  // ... some other stuff
}

it would be nice if we could build match_arms inline in the quote, something like

quote! {
   // ... some other stuff
  match x {
    # {
      my_enum.variants.iter().fold(TokenStream::new(), |mut t, v| {
        let ident = &v.ident;
        t.extend(quote! { #ident => /* something */ });
        t
      })
    }
  }
  // ... some other stuff
}

or have it support a block that returns an iterator

quote! {
   // ... some other stuff
  match x {
    # {
      my_enum.variants.iter().map(|v| {
        quote! { #{ &v.ident } => /* something */ })
      })
    }
  }
  // ... some other stuff
}

If you have alternative approach I am happy to discuss as well. I haven't looked into the implementation details, just thinking about this from the user's perspective. Not sure how easy/hard this would be to implement but I am happy to look into that as well if you think this is worth pursuing

dtolnay commented 4 months ago

Per https://github.com/dtolnay/quote/pull/276#pullrequestreview-2105173018, I would prefer not to support this. Thanks anyway!

Pistonight commented 4 months ago

Ah, I tried to search for discussions on this in issues and didn't find any. I wonder if it would be worth to include a note that this will not be supported in the doc comment?