rec_find_map

Macro rec_find_map 

Source
macro_rules! rec_find_map {
    ($in_list:expr, $($func:tt)*) => { ... };
}
Expand description

Helper for writing const fn equivalents of NList::find_map

This macro acts like a function with this signature:

use nlist::{NList, PeanoInt};

use nlist::receiver::Receiver;

fn rec_find_map<'a, P, T, L, F, U>(list: P , func: F) -> Option<U>
where
    P: Receiver<'a, NList<T, L>>,
    L: PeanoInt,
    T: 'a,
    F: FnOnce(
        ... // parameter types explained below
    ) -> Option<U>

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>)

§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.

§Example

§By reference

Example that takes an NList by reference

use nlist::{NList, Peano, PeanoInt, nlist};
 
const EMPTY: Option<i128> = finder(&nlist![]);
assert!(EMPTY.is_none());

const FOUND: Option<i128> = finder(&nlist![3, 5, 9]);
assert_eq!(FOUND, Some(1));
 
 
const fn finder<L>(list: &NList<u128, L>) -> Option<i128>
where
    L: PeanoInt
{
    nlist::rec_find_map!{list, |elem: &u128, next| {
        if *elem % 4 == 1 {
            Some((*elem / 4) as i128)
        } else {
            finder(next)
        }
    }}
}

§By value

Example that takes an NList of Copy elements by value

use nlist::{NList, Peano, PeanoInt, nlist};
 
use std::mem::ManuallyDrop as MD;
 
const EMPTY: Option<u8> = finder(nlist![]);
assert!(EMPTY.is_none());

const FOUND: Option<u8> = finder(nlist![3, 5, 9]);
assert_eq!(FOUND, Some(1));
 
 
const fn finder<L>(list: NList<u128, L>) -> Option<u8>
where
    L: PeanoInt
{
    nlist::rec_find_map!{list, |elem: u128, next| {
        // works around "destructor cannot be evaluated at compile-time" error
        let next = next.assert_copy();

        if elem % 4 == 1 {
            Some((elem % 4) as u8)
        } else {
            finder(MD::into_inner(next))
        }
    }}
}