#clone #utility-macro #macro #utility

clone-macro

Super simple utility macro for cloning before moving into a move closure/block

1 unstable release

0.1.0 May 9, 2022

#1784 in Rust patterns

Download history 290/week @ 2023-12-18 243/week @ 2023-12-25 234/week @ 2024-01-01 363/week @ 2024-01-08 497/week @ 2024-01-15 332/week @ 2024-01-22 266/week @ 2024-01-29 323/week @ 2024-02-05 205/week @ 2024-02-12 163/week @ 2024-02-19 235/week @ 2024-02-26 210/week @ 2024-03-04 224/week @ 2024-03-11 196/week @ 2024-03-18 410/week @ 2024-03-25 314/week @ 2024-04-01

1,165 downloads per month
Used in 13 crates (8 directly)

MIT license

9KB

clone-macro

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!(/* ... */);

Syntax

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

Examples

Basic Usage

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);

Advanced Usage

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

No runtime deps