Friday, May 29, 2020

Rust macro to clone many objects at once

When working at my forthcoming Rust Win32 library, I was frustrated with the unergonomic task of cloning all the objects before referencing them inside a closure. The basic problem goes like this:

let a = a.clone();
let b = b.clone();
stuff.do_something(|| {
  a.foo();
  b.bar();
});

It would be nice to have some kind of syntactic sugar. Then at some point I saw an example that led me to use destructuring, very familiar from my JavaScript experience:

let (a, b) = (a.clone(), b.clone());
stuff.do_something(|| {
  a.foo();
  b.bar();
});

After that, it came to my mind that I could write a macro for that. After about a half hour wrapping my head around the concept, I finally came up with a macro to clone many objects at once:

macro_rules! clone {
  ( $($obj: expr),+ ) => {{
    ( $( $obj.clone() ),+ )
  }};
}

Which finally allowed me to write the most sugary version of all:

let (a, b) = clone!(a, b);
stuff.do_something(|| {
  a.foo();
  b.bar();
});

Testable in the Rust Playground.