Trait tuplez::foreach::Mapper

source ·
pub trait Mapper<T> {
    type Output;
    type NextMapper;

    // Required method
    fn map(self, value: T) -> (Self::Output, Self::NextMapper);
}
Expand description

Define mappers for traversing the tuple.

To traverse a tuple with type Tuple<T0, T1, ... Tn>, you need to construct a custom mapper type, which implements Mapper<T0>, Mapper<T1>Mapper<Tn>. Pass your mapper to tuple’s foreach() method, then the tuple will call mapper’s map() method in order of its elements and move the elements in.

NOTE: Traversing a tuple will consume it. If this is not what you want, call as_ref() or as_mut() to create a new tuple that references its all members before traversing.

Tip: Mapper map elements by their types. If you are looking for a way to map elements by their order, then what you are looking for is to pass a tuple containing callable objects into fold() method.

§Quickly build a mapper by macros

Here are two ways you can quickly build a folder.

§Traverse tuples by element types

The mapper! macro helps you build a mapper that traverses tuples according to their element types.

For example:

use tuplez::{mapper, tuple, TupleLike};

let tup = tuple!(1, "hello", 3.14).foreach(mapper! {
    |x: i32| -> i64 { x as i64 }
    |x: f32| -> String { x.to_string() }
    <'a> |x: &'a str| -> &'a [u8] { x.as_bytes() }
});
assert_eq!(tup, tuple!(1i64, b"hello" as &[u8], "3.14".to_string()));

§Traverse tuples in order of their elements

You can create a new tuple with the same number of elements, whose elements are all callable objects that accepts an element and returns another value (FnOnce(T) -> U), then, you can use that tuple as a mapper.

use tuplez::{tuple, TupleLike};

let tup = tuple!(1, 2, 3);
let result = tup.foreach(
    tuple!(
        |x| x as f32,
        |x: i32| x.to_string(),
        |x: i32| Some(x),
    )
);
assert_eq!(result, tuple!(1.0, "2".to_string(), Some(3)));

§Custom mapper

For more complex cases that cannot be covered by the mapper! macro, for example, you want to save some results into context variables, you need to implement Mapper<Ti> for your mapper for all element type Tis in tuples. Generic can be used.

For example:

use tuplez::{foreach::Mapper, tuple, TupleLike};

struct MyElement(i32);

struct Collector<'a>(&'a mut Vec<String>);

impl<T: ToString> Mapper<&T> for Collector<'_> {
    type Output = ();
    type NextMapper = Self;
    fn map(self, value: &T) -> (Self::Output, Self::NextMapper) {
        (
            self.0.push(format!(
                "{} : {}",
                std::any::type_name::<T>(),
                value.to_string()
            )),
            self,
        )
    }
}

impl Mapper<&MyElement> for Collector<'_> {
    type Output = ();
    type NextMapper = Self;
    fn map(self, value: &MyElement) -> (Self::Output, Self::NextMapper) {
        (self.0.push(format!("MyElement : {}", value.0)), self)
    }
}

let mut buffers = vec![];
let collector = Collector(&mut buffers);
tuple!(1, "hello", MyElement(14))
    .as_ref()
    .foreach(collector);
assert_eq!(
    buffers,
    vec![
        "i32 : 1".to_string(),
        "&str : hello".to_string(),
        "MyElement : 14".to_string()
    ]
);

Required Associated Types§

source

type Output

Output type of mapping.

source

type NextMapper

Type of next mapper to be use.

Required Methods§

source

fn map(self, value: T) -> (Self::Output, Self::NextMapper)

Map an element to another value.

Implementors§

source§

impl<First, F, Out, FOthers> Mapper<First> for Tuple<F, FOthers>
where F: FnOnce(First) -> Out, FOthers: TupleLike,

§

type Output = Out

§

type NextMapper = FOthers