A simple macro to make cloning data before passing it into a move
closure or block.
This macro is intentionally designed to be compatible with
rustfmt
formatting.
You can use this macro throughout your crate without needing to explicitly import it every time as follows:
#[macro_use]
extern crate clone_macro;
/* ... */
clone!(/* ... */);
Otherwise, you can use
it as normal.
use clone_macro::clone;
/* ... */
clone!(/* ... */);
The clone!
macro takes a comma separated list of either one of two forms
which can have an optional mut
prefix modifier, followed by an arbitrary
expression.
For example, the following is a valid call
let a = 1;
let b = 2;
clone!([mut a, b], ());
and desugars down to:
let a = 1;
let b = 2;
{
let mut a = a.clone();
let b = b.clone();
()
};
The clone list can also take a second form, which is an arbitrary expression
followed by as
and the name of the variable. For example:
let s = "Hello, there!";
clone!([{ s.len() } as len], move || {
assert_eq!(len, "Hello, there!".len());
});
The above desugars into:
let s = "Hello, there!";
{
let len = "Hello, there!".len();
move || {
assert_eq!(len, "Hello, there!".len());
}
};
This macro is most useful when the second argument is a closure, and is what it is intended to work with, though not strictly so.
All forms mentioned above can be mixed and matched, including adding a mut
modifier
for the second form as:
mut { $expr } as $ident
use clone_macro::clone;
let s = "You are a beautiful being!".to_string();
let c = clone!([s], move || {
println!("{s}");
});
c();
// `s` wasn't directly moved, rather, cloned first, then moved; therefore,
// we can still use `s`
assert_eq!(s.as_str(), "You are a beautiful being!");
We can also declare the cloned move
as mut
:
use clone_macro::clone;
let a = 7;
let b = 0;
let d = 12;
le
t mut c = clone!([a, mut b, d], move || {
b = 42 - a - d;
println!("a + b + d = {}", a + b + d);
});
c();
assert_eq!(a, 7);
assert_eq!(b, 0);
assert_eq!(d, 12);
We can clone arbitrary expressions:
use clone_macro::clone;
struct MyStruct {
some_field: String,
}
let s = MyStruct {
some_field: "Beyond measure.".to_string(),
};
let mut c = clone!([{ s.some_field } as some_field, mut { s.some_field } as mut_some_field], move || {
mut_some_field.clear();
assert!(mut_some_field.is_empty());
assert_eq!(some_field.as_str(), "Beyond measure.");
});
c();
assert_eq!(s.some_field.as_str(), "Beyond measure.");
License: MIT