Defer macros and utils for Rust
Deferred execution Rust utilities.
This crate provides utility structs and macros for deferred execution of code in Rust. It allows you to specify actions that should be executed when a scope is exited, such as when a function ends or a block of code completes execution.
Features
-
Defer Statements: The library introduces the concept of
Defer
ed statements, providing similar functionality to those found in other programming languages. TheDefer
struct allows you to register functions or closures to be executed when the active scope is exited. -
DeferGroup: The
DeferGroup
struct allows you to group multiple deferred actions together. When theDeferGroup
goes out of scope, all registered actions are executed in reverse order. -
Macro Support: The
defer!
anddefer_scope!
macros simplify the process of creating deferred actions. They can be used to defer function calls, closures, or arbitrary code blocks.
Installation
To use the defer
library, add it as a dependency in your Cargo.toml
:
[]
= "0.1"
Usage
1. Using defer!
Macro
The defer!
macro simplifies the creation of deferred actions. It supports both function calls and arbitrary code blocks.
Example:
use defer;
defer!;
// ... other code ...
// The deferred action will be executed when it goes out of scope
2. Using defer_scope!
Macro
The defer_scope!
macro can be used in conjunction with the defer_scope_init!
macro to precisely manage the scope in which a collection of deferred statements will execute at the end of.
Example:
use ;
use Cell;
let val = new;
assert_eq!
3. Using Defer
Struct
The Defer
struct is used to create individual deferred actions. You can create a new deferred action by providing a closure or function that takes no arguments. When the Defer
instance goes out of scope, the provided closure or function will be executed.
Note: The defer!
macro is syntactic sugar for this struct.
Example:
use Defer;
let deferred_action = new;
// ... other code ...
// deferred_action will be executed when it goes out of scope
4. Grouping Deferred Actions
The DeferGroup
struct allows you to group multiple deferred actions together. Actions are executed in reverse order when the DeferGroup
goes out of scope.
Note: The defer_scope!
and defer_scope_init!
macros are syntactic sugar for this struct and it's ::add()
method.
Example:
use DeferGroup;
let mut defer_group = new;
defer_group.add;
defer_group.push;
// ... other code ...
// Both deferred actions will be executed in reverse order
5. Macros Special Case: Capturing closure’s environment by value
Prefixing the statement(s) in a 'defer!' or 'defer_scope!' macro with the move
keyword will capture the closure’s environment by value.
Note: This is the same as adding move
to the closure passed to Defer::new()
or DeferGroup::add()
.
Example:
use ;
let val = "Variable that must be passed by value!";
defer_scope_init!; // Initiate scoped deferred collection
6. Macros Special Case: Immediate evaluation of passed arguments
It's sometimes desireable to have the arguments passed to a deferred function call be evaluated at time of deferment, rather than the deferred time of execution (similar to how the defer
keyword works in Go
and other programming languages), this behavior is mimicked when the 'defer!' (or 'defer_scope!') macro is used on a solitary function call.
Note: This behavior can be disbled by simply postfixing the function call passed to the macro by a ;
.
Example:
use ;
use ;
use Write;
let buff = new;
let buff2 = new;
let val = new;
defer_scope_init!;
defer_scope ! ;
// This will evaluate the arguments passed to the invoked at function at call time (deferred-to time / later), `val.get()` results in `3`
defer_scope!;
// This will evaluate the arguments passed to the invoked function at time of macro invocation (now), `val.get()` results in `0`
defer_scope!;
val.set;
Lengthy Example
use ;
use Cell;
This will result in the following lines being printed to stdout
:
This will be printed 1st, x is: 1
This will be printed 2nd
This will be printed 3rd
This will be printed 4th
This will be printed 5th
This will be printed 6th
This will be printed 7th
This will be printed 8th, x is: 3
This will be printed 9th
This will be printed 10th, x is: 0
This will be printed 11th
This will be printed 12th
This will be printed 13th/last