capture-it 
See example
For detailed documentation, see capture_it::capture
Usage
Creates closures with a syntax similar to modern C++'s lambda capture rules. The first argument to
the capture! macro is an array listing the arguments to be captured by the closure, and the second
argument specifies either an 'async move' block or a 'move' closure. (to more explicitly indicate
that the move closure is used, a compile-time error is raised for any async or closure
function missing the move tag).
The following example demonstrates how to create a generator closure by capturing an arbitrary expression (=0) with the index identifier.
use capture;
// You can capture an expression, as we do in c++'s lambda capture.
//
// Any identifier prefixed with *(asterisk) declared as mutable.
let mut gen = capture!;
assert!;
Since the function arguments of the capture macro must use the move closure, reference captures must be explicitly listed; they are represented by the & or &mut prefix, as in normal rust syntax.
use capture;
let mut num = 0;
let mut gen = capture!;
assert!;
The capture! macro calls Clone::clone for every argument passed in, by default. This is a more
ergonomic way to create closures.
use capture;
use ;
let arc = new;
// From this ...
spawn;
// To this
spawn;
// The naive spin wait ...
while strong_count > 1
assert_eq!;
This macro is particularly useful when you need to pass multiple Arc instances through Clone to different closures. Take a look at the following example to see how it simplifies traditional block capture.
use capture;
use Arc;
let arc = new;
let arc2 = arc.clone; // let's just think these are all different variables
let arc3 = arc.clone;
let arc4 = arc.clone;
let while_strong_count = ;
// Before, when you have to capture variables by copy ...
spawn;
// Then, we can write same logic with above, but in much more concise way
spawn;
assert!;
// as all variables are captured by clone, we can still owning `arc*` series
drop;
while_strong_count;
All variables other than those specified in the capture list follow the normal closure rules for rust, so if you need to take ownership of a variable, simply remove its name from the capture list.
use capture;
use Arc;
let cloned = new;
let moved = cloned.clone;
spawn;
// 'moved' was moved. So we cannot use it here.
// drop(moved);
while strong_count > 1
Asynchronous blocks follow the same rules.
use capture;
use ;
let = ;
let task1 = capture!;
let task2 = capture!;
drop; // we still have ownership of tx
task2.await;
task1.await;
for val in .chain
Bonus
The capture macro contains several syntactic sugars. For example, if you want to capture the type
&str as the corresponding ToOwned type, String, you can apply the Own(..) decorator.
use capture;
let hello = "hello, world!";
let mut gen = capture!;
assert_eq!;
assert_eq!;
assert_eq!;
The Weak decorator is used to capture a downgraded instance of Arc or Rc.
use capture;
use Rc;
use Arc;
let rc = new;
let arc = new;
let closure = capture!;
drop; // Let weak pointer upgrade of 'rc' fail
closure;
The Some decorator is useful to mimic FnOnce in the FnMut function.
use capture;
let initial_value = ;
let mut increment = 0;
let mut closure = capture!;
closure;
closure;
closure;
assert_eq!;
Any other function call with single argument can be used as a decorator. For example, the normal
clone representation of the capture macro is replaced by Clone::clone(var).
use capture;
let clone1 = new;
let clone2 = clone1.clone;
// following capture statement, `clone1` and `Clone::clone(&clone2)` behave equivalent.
let closure = capture!;
closure;
Alternatively, you can capture the return value of a function called on self as the name of its
variable. Function calls can contain parameters, but there are some restrictions; for example,
re-chaining to a function's return value will not work (var.foo().bar()....). Only one function
call is allowed.
Decorators are useful for capturing simple type changes; if you want to capture complex expressions, it's best to use the assignment syntax of a=b.
use ;
use capture;
let arc = new;
let rc = new;
let weak_arc = downgrade;
let weak_rc = downgrade;
drop;
// The return value of `.upgrade()` will be captured as of its name.
let closure = capture!;
closure;
Trivia
Other closure crates use a more intuitive capture syntax...
For example, the (move a, ref b, clone b, ...) grammar in the closure crate can express closure parameters more intuitively.
On the other hand, the * prefix to express the mutability of capture-it is unintuitive and hard to understand - why did we do it this way?
Introducing new grammars is a very tempting option, but by default, most of these attempts are poorly understood by the rustfmt utility.
Since closure macros typically pass the function body as a macro argument, a fairly long body can lose the benefit of the formatter if the rustfmt parser fails to parse the macro argument.
On the other hand, the capture_it::capture macro is a perfectly valid rust syntax (at least syntactically) that simply passes an array and a single function block as macro arguments. (Also, a capture list wrapped in [square brackets] can be used in a similar sense to C++.)
So any capture and function block you define in the capture_it::capture macro can be formatted by rustfmt, which is something I personally find quite important.