Macro enclose::enclose

source ·
macro_rules! enclose {
    [
		// (a, b) move || true
		( $($enc_args:tt)* ) move || $($b:tt)*
	] => { ... };
    [
		// (a, b) move |c, d| true
		( $($enc_args:tt)* ) move | $($args:tt),* | $($b:tt)*
	] => { ... };
    [
		// (a, b) || true
		( $($enc_args:tt)* ) || $($b:tt)*
	] => { ... };
    [
		// (a, b) |c, d| true
		( $($enc_args:tt)* ) | $($args:tt),* | $($b:tt)*
	] => { ... };
    [
		// (a, b) true
		( $($enc_args:tt)* ) $($all:tt)*
	] => { ... };
    [] => { ... };
}
Expand description

A macro for creating a closure, as well as cloning, copying values into the closure.

§Args Support

A list of all possible arguments that can be written, separated by commas, in the arguments to the macro.

§.clone() operation

// (a => mut b: String) will be converted to (let mut b: String = a.clone();)
// (b => mut b)
// (a => b: usize)
// (a => b)
// (mut a: String)
// (mut a)
// (a: String)
// (a)

§*copy operation

// (*a => mut b: &str) will be converted to (let mut b: &str = *a;)
// (*a => mut b)
// (*a => b: &str)
// (*a => b)
// (mut *a: &str)
// (mut *a)
// (*a: &str)
// (*a)

§let ref mut a = b; (ref) operation

// (ref mut a: String) will be converted to (let ref mut a: String = a;)
// (ref mut a)
// (ref a: String)
// (ref a)
// (ref a => mut b: String)
// (ref a => mut b)
// (ref a => b: String)
// (ref a => b)

§(1+1) (expr) operation

// (@(1+1) => mut b: usize) will be converted to (let mut b: usize = (1+1);)
// (@(1+1) => mut b)
// (@(1+1) => b: usize)
// (@(1+1) => b)

§let a = b; (move) operation

// (move a => mut b: String) will be converted to (let mut b: String = a;)
// (move a => mut b)
// (move a => mut b)
// (move a => b: String)
// (move a => b)
// (move mut a: String)
// (move mut a)
// (move a: String)
// (move a)

§{println!("test");} (run) operation

// { panic!("12"); }

§Example

§JustUse

use enclose::enclose;

fn main() {
   let clone_data = 0;
   let add_data = 100;

   my_enclose(enclose!((mut clone_data, add_data) || {
   	// (mut clone_data, add_data) ->
   	// let mut clone_data = clone_data.clone();
   	// let add_data = add_data.clone();

   	println!("#0 {:?}", clone_data);
   	clone_data += add_data;
   	println!("#1 {:?}", clone_data);

   	assert_eq!(clone_data, 100);
   }));

   assert_eq!(clone_data, 0);
}

#[inline]
fn my_enclose<F: FnOnce() -> R, R>(a: F) -> R {
   a()
}

§Expr

use enclose::enclose;
use std::sync::Arc;

fn main() {
	let clone_data = Arc::new(0);
	let add_data = Arc::new(100);

	// I also note that any expressions can be used, but the main thing is to
	// put the @ symbol at the beginning of the variable, and not forget to assign
	// a new name to the variable using =>.
	my_enclose(
		enclose!((@*clone_data => mut clone_data: usize, @*(add_data.clone()) => add_data) || {
			// (@*clone_data => mut clone_data, @*(add_data.clone()) => add_data) ->
			// let mut clone_data = *clone_data;
			// let add_data = *(add_data.clone());

			println!("#0 {:?}", clone_data);
			clone_data += add_data;
			println!("#1 {:?}", clone_data);

			assert_eq!(clone_data, 100);
		}),
	);

	assert_eq!(*clone_data, 0);
}

#[inline]
fn my_enclose<F: FnOnce() -> R, R>(a: F) -> R {
	a()
}