#![feature(
lazy_type_alias,
try_trait_v2_residual,
try_trait_v2,
type_alias_impl_trait,
tuple_trait,
import_trait_associated_functions,
never_type,
iter_next_chunk
)]
#![no_std]
#![allow(mixed_script_confusables, confusable_idents)]
//! 
//!
//! start with [`Tupl`].
mod implementations;
mod iterator;
mod picks;
pub use iterator::{
IteratorOfMutableReferencesToTuple,
IteratorOfMutableReferencesToTupleWithF, IteratorOfReferencesToTuple,
IteratorOfReferencesToTupleWithF, IteratorOfTuples,
IteratorOfTuplesWithF, hrf,
};
pub mod fns;
mod r#try;
pub use r#try::{TryRefMutTuple, TryRefTuple, TryTuple};
/// Reverse a tuple.
pub trait Reverse: Tupl {
type Reversed: Tupl;
fn reverse(self) -> Self::Reversed;
}
#[doc(inline)]
pub use Reverse::{reverse, reverse as flip};
#[doc(inline)]
pub use Tupl::{
drop, head, head as left, head as fst, last, last as right, pick, take,
};
pub use picks::*;
/// Construct a tuple.
pub fn cons<T, Tup: Cons<T>>(x: T, y: Tup) -> Tup::Cons {
Tup::Cons::cons(x, y)
}
/// Construct a tuple, backwards.
pub fn snoc<T, Tup: Cons<T>>(x: Tup, y: T) -> Tup::Snoc {
Tup::Snoc::snoc(x, y)
}
/// alias for [`snoc`]
pub trait Push<T>: Tupl {
type Result;
/// ```
/// use ttools::*;
/// let x = (1, 2).push(3);
/// assert_eq!(x, ((1, 2, 3)));
/// ```
fn push(self, other: T) -> Self::Result;
}
/// alias for [`cons`]
pub trait With<T: Tupl> {
type Result;
/// ```
/// use ttools::*;
/// let x = 1.with((2, 3));
/// assert_eq!(x, ((1, 2, 3)));
/// ```
fn with(self, other: T) -> Self::Result;
}
// implemented for the constructed type
pub trait Cons<T>: Tupl {
/// (T, ..self)
type Cons: Tupl<Head = T, Tail = Self>;
/// (..self, T)
type Snoc: Tupl<Last = T, Init = Self>;
}
/// backing trait for [`take`].
pub trait TD<const N: usize>: Tupl {
/// self[N..]
type Drop: Tupl;
/// self[..N]
type Take: Tupl;
// self[LEN - N..]
type TakeB: Tupl;
/// self[..LEN - N]
type DropB: Tupl;
/// deconstruct
fn dropf(self) -> (Self::Take, Self::Drop);
/// deconstruct
fn dropb(self) -> (Self::DropB, Self::TakeB);
}
/// backing trait for [`pick`]
pub trait Pick<const N: usize>: Tupl {
/// `self[N]`
type At;
/// self[..N]
type L: Tupl;
/// self[N + 1..]
type R: Tupl;
/// self::L + Self::R
type Delete: Tupl;
/// without Self::At
fn delete(l: Self::L, r: Self::R) -> Self::Delete;
/// reconstruct
fn repick(l: Self::L, at: Self::At, r: Self::R) -> Self;
/// deconstruct
fn depict(self) -> (Self::L, Self::At, Self::R);
}
pub trait RePick<const N: usize, T>: Pick<N> + Sized {
type New: Tupl;
fn unpick(l: Self::L, at: T, r: Self::R) -> Self::New;
}
/// trait for mapping all elements of a tuple
pub trait MapAll<R: Tupl, Fns: Tupl>: Sized {
fn map_all(self, functions: Fns) -> R;
}
/// trait for mapping all elements of a tuple (FnMut edition).
pub trait MapAllMut<R: Tupl, Fns: Tupl> {
fn map_all_mut(self, functions: &mut Fns) -> R;
}
/// Main tuple trait.
#[diagnostic::on_unimplemented(
label = "this is not a tuple, or it is too big a tuple (>26 elements)"
)]
pub trait Tupl: core::marker::Tuple {
/// Refer to listmonster.
type Head;
/// Refer to listmonster.
type Last;
/// Refer to listmonster.
type Tail: Tupl;
/// Refer to listmonster.
type Init: Tupl;
/// Middle section of listmonster.
type Inner: Tupl;
/// Size of tuple.
const LEN: usize;
/// Note: Partial function.
#[doc(alias = "left")]
fn head(self) -> Self::Head
where
Self: Sized,
{
self.uncons().0
}
/// Note: Partial function.
#[doc(alias = "right")]
fn last(self) -> Self::Last
where
Self: Sized,
{
self.unsnoc().1
}
/// Note: Partial function.
fn take<const N: usize>(self) -> Self::Take
where
Self: TD<N> + Sized,
{
self.dropf().0
}
/// Note: Partial function.
fn drop<const N: usize>(self) -> Self::Drop
where
Self: TD<N> + Sized,
{
self.dropf().1
}
/// Note: Partial function.
fn take_back<const N: usize>(self) -> Self::TakeB
where
Self: TD<N> + Sized,
{
self.dropb().1
}
/// Note: Partial function.
fn drop_back<const N: usize>(self) -> Self::DropB
where
Self: TD<N> + Sized,
{
self.dropb().0
}
/// Gives you the element at index N (from 0).
/// Note: partial function
fn pick<const N: usize>(self) -> Self::At
where
Self: Pick<N> + Sized,
{
self.depict().1
}
/// unconstructs self, returning head and tail (see listmonster)
fn uncons(self) -> (Self::Head, Self::Tail);
/// untcurtsnocs self, returning init and last (see listmonster)
fn unsnoc(self) -> (Self::Init, Self::Last);
/// weird thing, full construct
fn fcons(
start: Self::Head,
inner: Self::Inner,
last: Self::Last,
) -> Self;
type AsRef<'a>: Tupl
where
Self: 'a;
fn as_ref(&self) -> Self::AsRef<'_>;
type AsMut<'a>: Tupl
where
Self: 'a;
fn as_mut(&mut self) -> Self::AsMut<'_>;
/// reconstruct; dont use directly
fn cons(head: Self::Head, tail: Self::Tail) -> Self;
/// retcurtsnoc; dont use directly
fn snoc(init: Self::Init, last: Self::Last) -> Self;
}
#[test]
fn t() {
2.with(cons(4i8, (1i16, 2i32)).push(2))
.take::<2>()
.push(4)
.push(0u8)
.pick::<3>();
assert_eq!(
(1, 2u8, 3u16, "4").map_all((
|_| {},
|x| x + 1,
|x| x / 3,
|x| x.parse::<u32>().unwrap(),
)),
((), 3, 1, 4)
);
}