macro_rules! using {
($target:expr => { $( $t:tt )* }) => { ... };
($id:ident @ $target:expr => { $( $t:tt )* }) => { ... };
}
Expand description
A macro that provides method cascading for an object.
§Usage
using!(expression => { ... })
using!(identifier @ expression => { ... })
Binds expression
to a mutable variable (called “target”) that can be manipulated inside the
block with expressions starting with a dot (called “target expressions”). The target variable
can be explicitly named with an @-binding. If the block does not contain a trailing expression,
the target is returned instead.
Target expression are a sequence of field accessess (e.g. .x
) and method calls (e.g.
.push(10)
) and can only be used in blocks, let statements, bodies of if expressions, match
expressions, and loops. They cannot be used in the conditional expressions and also not in
compound expressions, e.g. .last().unwrap() + 1
is not valid. For details see below.
Besides the target expressions, every statement and expression can be used inside the block,
which also allows nesting using
macros.
§Examples:
let hello_world = using!(Vec::new() => {
.push("Hello");
.push("World!");
.join(", ")
});
assert_eq!(hello_world, "Hello, World!");
// Generated code:
//
// let hello_world = {
// let mut target = Vec::new();
// target.push("Hello");
// target.push("World!");
// target.join(", ")
// };
More complicated example with for
, if
, and let
:
let vec = using!(Vec::new() => {
for i in 0..10 {
if i % 2 == 0 {
.push(i);
}
}
let sum = .iter().sum();
.push(sum);
});
assert_eq!(&vec[..], [ 0, 2, 4, 6, 8, 20 ]);
§Syntax:
This section explains the syntax in a BNF-like form to clarify the details and where target
expressions can be used. The symbols IDENTIFIER
, Statement
, Expression
,
BlockExpression
, Pattern
, GenericArgs
, CallParams
, and Type
are defined in The Rust
Reference. The syntax of the macro is defined by:
"using" "!" "(" Expression "=>" UsingBlock ")"
"using" "!" "(" IDENTIFIER "@" Expression "=>" UsingBlock ")"
A UsingBlock
is an extension of Rusts BlockExpression
: it is a block surrounded by curly
braces, containing a sequence of UsingStatement
s followed by an optional UsingExpression
.
A UsingStatement
is either a Statement
or one of the following:
UsingExpression ";"
"let" IDENTIFIER ( ":" Type )? = UsingExpression ";"
A UsingExpression
is either an Expression
or one of the following:
UsingBlock
// This defines the "target expressions"
( "." IDENTIFIER | "." IDENTIFIER ( "::" GenericArgs )? "(" CallParams? ")" )+
"if" Expression UsingBlock ( "else" "if" Expression UsingBlock )* ( "else" UsingBlock )?
"match" Expression "{" ( Pattern ( "if" Expression )? => ( UsingBlock | UsingExpression "," ) )* "}"
"loop" UsingBlock
"while" Pattern "in" Expression UsingBlock
"for" Pattern "in" Expression UsingBlock