Skip to content

jquesada2016/clone-macro-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

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

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages