macro_rules! fn_equivalent {(
fn_name = $fn_name:literal
fn_ret = $fn_ret:literal
closure_ret = $closure_ret:literal
$(additional_generics=$additional_generics:literal)?
$(additional_params=$additional_params:literal)?
$(additional_args=$additional_args:literal)?
) => {concat!("
This macro acts like a function with this signature:
```rust
use nlist::{NList, PeanoInt};
use nlist::receiver::Receiver;
# use nlist::receiver::HktApply;
fn ", $fn_name,"<'a, P, T, L, F",
$(", ", $additional_generics,)?
">(list: P ", $(", ", $additional_params,)? ", func: F) -> ", $fn_ret,"
where
P: Receiver<'a, NList<T, L>>,
L: PeanoInt,
T: 'a,
F: FnOnce(
# /*
... // parameter types explained below
# */
# HktApply<'a, P::Hkt, T>,
# HktApply<'a, P::Hkt, NList<T, L::SubOneSat>>
) -> ", $closure_ret, "
# { nlist::", $fn_name,"!{ list ", $(", ", $additional_args,)? ", |a, b| { func(a, b) }} }
```
The closure is only called when the list is non-empty (i.e.: when `L != 0`).
The closure parameters depend on the value of `P`:
- If `P == NList<T, L>`: the parameters are `(T, Nlist<T, L::SubOneSat>)`
- If `P == &NList<T, L>`: the parameters are `(&T, &Nlist<T, L::SubOneSat>)`
- If `P == &mut NList<T, L>`: the parameters are `(&mut T, &mut Nlist<T, L::SubOneSat>)`
")}}
use fn_equivalent;
macro_rules! early_termination_warning {() => {"
# Note
Because iteration over the list might terminate before the list is fully consumed,
by-value iteration over non-Copy types does not work in const,
and by-value iteration over Copy types requires doing what the by-value example does.
"}}
use early_termination_warning;
#[doc = fn_equivalent!(
fn_name = "rec_all"
fn_ret = "bool"
closure_ret = "bool"
)]
#[doc = early_termination_warning!()]
#[macro_export]
macro_rules! rec_all {
($in_list:expr, $($func:tt)*) => {
$crate::__parse_closure_2_args!{__rec_all ($in_list,) $($func)*}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __rec_all {
(
$in_list:expr,
|$elem:tt: $elem_ty:ty, $next:tt: $next_ty:ty| -> $ret_ty:ty $block:block
) => {
$crate::__rec_shared!{
$in_list,
len_te,
|| true,
|$elem: $elem_ty, $next: $next_ty| {
let ret: $ret_ty = $block;
let _: $crate::__::bool = ret;
ret
}
}
}
}
#[doc = fn_equivalent!(
fn_name = "rec_any"
fn_ret = "bool"
closure_ret = "bool"
)]
#[doc = early_termination_warning!()]
#[macro_export]
macro_rules! rec_any {
($in_list:expr, $($func:tt)*) => {
$crate::__parse_closure_2_args!{__rec_any ($in_list,) $($func)*}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __rec_any {
(
$in_list:expr,
|$elem:tt: $elem_ty:ty, $next:tt: $next_ty:ty| -> $ret_ty:ty $block:block
) => {
$crate::__rec_shared!{
$in_list,
len_te,
|| false,
|$elem: $elem_ty, $next: $next_ty| {
let ret: $ret_ty = $block;
let _: $crate::__::bool = ret;
ret
}
}
}
}
#[doc = fn_equivalent!(
fn_name = "rec_find_map"
fn_ret = "Option<U>"
closure_ret = "Option<U>"
additional_generics="U"
)]
#[doc = early_termination_warning!()]
#[macro_export]
macro_rules! rec_find_map {
($in_list:expr, $($func:tt)*) => {
$crate::__parse_closure_2_args!{__rec_find_map ($in_list,) $($func)*}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __rec_find_map {
(
$in_list:expr,
|$elem:tt: $elem_ty:ty, $next:tt: $next_ty:ty| -> $ret_ty:ty $block:block
) => {
$crate::__rec_shared!{
$in_list,
len_te,
|| None,
|$elem: $elem_ty, $next: $next_ty| {
let ret: $ret_ty = $block;
let _: Option<_> = ret;
ret
}
}
}
}
#[doc = fn_equivalent!(
fn_name = "rec_map"
fn_ret = "NList<U, L>"
closure_ret = "(U, NList<U, L::SubOneSat>)"
additional_generics="U"
)]
#[macro_export]
macro_rules! rec_map {
($in_list:expr, $($func:tt)*) => {
$crate::__parse_closure_2_args!{__rec_map ($in_list,) $($func)*}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __rec_map {
(
$in_list:expr,
|$elem:tt: $elem_ty:ty, $next:tt: $next_ty:ty| -> $ret_ty:ty $block:block
) => {
$crate::__rec_shared!{
$in_list,
len_te,
|| $crate::NList::nil().coerce_len(len_te.flip()),
|$elem: $elem_ty, $next: $next_ty| {
$crate::__::destructure!{(elem, next): $ret_ty = $block}
$crate::NList::cons(elem, next).coerce_len(len_te.flip())
}
}
}
}
#[doc = fn_equivalent!(
fn_name = "rec_for_each"
fn_ret = "()"
closure_ret = "()"
)]
#[macro_export]
macro_rules! rec_for_each {
($in_list:expr, $($func:tt)*) => {
$crate::__parse_closure_2_args!{__rec_for_each ($in_list,) $($func)*}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __rec_for_each {
(
$in_list:expr,
|$elem:tt: $elem_ty:ty, $next:tt: $next_ty:ty| -> $ret_ty:ty $block:block
) => {
$crate::__rec_shared!{
$in_list,
len_te,
|| (),
|$elem: $elem_ty, $next: $next_ty| {
let ret: $ret_ty = $block;
let _: () = ret;
}
}
}
}
#[doc = fn_equivalent!(
fn_name = "rec_fold"
fn_ret = "U"
closure_ret = "U"
additional_generics="U"
additional_params="accum: U"
additional_args="accum"
)]
#[macro_export]
macro_rules! rec_fold {
($in_list:expr, $accum:expr, $($func:tt)*) => {
$crate::__parse_closure_2_args!{__rec_fold ($in_list, $accum,) $($func)*}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __rec_fold {
(
$in_list:expr,
$accum:expr,
|$elem:tt: $elem_ty:ty, $next:tt: $next_ty:ty| -> $ret_ty:ty $block:block
) => {
$crate::__rec_shared!{
$in_list,
len_te,
|| $accum,
|$elem: $elem_ty, $next: $next_ty| {
let ret: $ret_ty = $block;
ret
}
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __rec_shared {
(
$in_list:expr,
$len_te:ident,
|| $on_nil:expr,
|$elem:tt: $elem_ty:ty, $next:tt: $next_ty:ty| $on_cons:block
) => {
match $in_list {in_list => {
match $crate::NList::len_proof($crate::receiver::as_ref(&in_list)) {
$crate::PeanoWit::Zero($len_te) => {
_ = $crate::NList::coerce_len_poly(in_list, $len_te);
$on_nil
}
$crate::PeanoWit::PlusOne($len_te) => {
$crate::__::destructure!{
($elem, $next) = $crate::NList::split_head_poly(
$crate::NList::coerce_len_poly(in_list, $len_te)
)
}
let _: $elem_ty = $elem;
let _: $next_ty = $next;
$on_cons
}
}
}}
}
}