macro_rules! crecurse {
(@macro_def ($dol:tt) $name:ident $($cargs:ident)*) => { ... };
(
@static [$(($cargs:ident, $cargsexpr:expr, $cargsty:ty))*] [$(,)?],
fn $func:ident ($($args:ident: $argsty:ty),* $(,)?) -> $ret:ty $body:block
) => { ... };
(@static [$($pcaps:tt)*] [$(,)?], fn $func:ident ($($argstt:tt)*) $($rest:tt)*) => { ... };
(@static [$($pcaps:tt)*] [$carg:ident: &mut $cargty:ty, $($caps:tt)*], $($rest:tt)*) => { ... };
(@static [$($pcaps:tt)*] [$carg:ident: &$cargty:ty, $($caps:tt)*], $($rest:tt)*) => { ... };
(@static [$($pcaps:tt)*] [$carg:ident: $cargty:ty, $($caps:tt)*], $($rest:tt)*) => { ... };
($([$($caps:tt)*],)? static fn $func:ident ($($args:ident: $argsty:ty),* $(,)?) $($rest:tt)*) => { ... };
(
@default [$($cargs:ident: $cargsty:ty),* $(,)?],
fn $func:ident ($($args:ident: $argsty:ty),* $(,)?) -> $ret:ty $body:block
) => { ... };
(@default [$($caps:tt)*], fn $func:ident ($($argstt:tt)*) $($rest:tt)*) => { ... };
($([$($caps:tt)*],)? fn $func:ident ($($args:ident: $argsty:ty),* $(,)?) $($rest:tt)*) => { ... };
(
@unsafe [$($cargs:ident: $cargsty:ty),* $(,)?],
fn $func:ident ($($args:ident: $argsty:ty),* $(,)?) -> $ret:ty $body:block
) => { ... };
(@unsafe [$($caps:tt)*], fn $func:ident ($($argstt:tt)*) $($rest:tt)*) => { ... };
($([$($caps:tt)*],)? unsafe fn $func:ident ($($args:ident: $argsty:ty),* $(,)?) $($rest:tt)*) => { ... };
($($t:tt)*) => { ... };
}
Expand description
Macro that returns a recursive function that (semi-)automatically captures.
§Example
default version
let mut res = 0usize;
let coeff = 3usize;
crecurse!(
// (1) semi-automatically capture mutable reference (res: &mut usize)
[res: usize],
fn mul(x: usize, y: usize) {
if y > 0 {
if y % 2 == 1 {
// (2) automatically capture reference (coeff: &usize)
*res += coeff * x;
}
// (3) call macro to recurse
mul!(x + x, y / 2);
}
}
)(10, 19); // (4) macro returns captured version of the recursive function
assert_eq!(res, coeff * 10 * 19);
unsafe version (automatically capture everything)
let mut res = 0usize;
let coeff = 3usize;
crecurse!(
unsafe fn mul(x: usize, y: usize) {
if y > 0 {
if y % 2 == 1 {
res += coeff * x;
}
mul!(x + x, y / 2);
}
}
)(10, 19);
assert_eq!(res, coeff * 10 * 19);
no overhead version (semi-automatically capture everything)
let mut res = 0usize;
let coeff = 3usize;
crecurse!(
[res: &mut usize, coeff: &usize],
static fn mul(x: usize, y: usize) {
if y > 0 {
if y % 2 == 1 {
*res += coeff * x;
}
mul!(x + x, y / 2);
}
}
)(10, 19);
assert_eq!(res, coeff * 10 * 19);
§Syntax
crecurse!(
([($ident: $type),*,?],)?
(unsafe|static)? fn $ident\(($ident: $type),*,?\) (-> $type)? $block
)