2 releases
0.1.1 | Feb 28, 2024 |
---|---|
0.1.0 | Feb 28, 2024 |
0.0.13 |
|
#1512 in Rust patterns
152 downloads per month
20KB
297 lines
tupley
Intro
Extension for primitive tuple (Hlist based on recursive structure).
You could use it to contain elements with different types.
Struct
Basic structure:
// NonEmpty Tuple
struct Tuple<First, Tail>(First, Tail);
// Empty Tuple used as last element
struct Unit;
trait TupleY {
const LEN: usize;
// ......
// ......
}
impl TupleY for Unit {
const LEN: usize = 0;
// ......
// ......
}
impl<First, Tail: TupleY> TupleY for Tuple<First, Tail> {
const LEN: usize = <Tail as TupleY>::LEN + 1;
// ......
// ......
}
use tupley::prelude::*;
let t = tup!(1, 2.0, false);
// Tuple(1, Tuple(2.0, Tuple(false, Unit)))
Usage
- generate new Tuple:
use tupley::prelude::*;
fn tuple_new() {
let t = tup!();
assert_eq!(t, Unit);
let t = tup!(1);
assert_eq!(t, Tuple(1, Unit));
let t = tup!(1, 2.0, "3");
assert_eq!(t, Tuple(1, Tuple(2.0, Tuple("3", Unit))));
}
- check empty:
use tupley::prelude::*;
fn tuple_is_empty() {
let t = tup!();
assert!(t.is_empty());
let t = tup!(1, false);
assert!(!t.is_empty());
}
- generate new Tuple type:
use tupley::prelude::*;
fn tuple_type() {
let t = <tup_t!(i32, &str, bool)>::default();
assert_eq!(t, tup!(0, "", false));
let t: tup_t!(i32, &str, bool) = Default::default();
assert_eq!(t, tup!(0, "", false));
#[derive(Default, Debug, PartialEq, Eq)]
struct Wrapper<'a> {
a: tup_t!(i32, i32),
b: tup_t!(&'a str, bool),
}
let t = Wrapper::default();
assert_eq!(t, Wrapper{
a: tup!(0, 0),
b: tup!("", false),
})
}
- generate Tuple pattern for macthing:
use tupley::prelude::*;
fn tuple_pattern() {
let t = tup!();
let tup_pat!() = t;
let t = tup!(1);
let tup_pat!(a) = t;
assert_eq!(a, tup!(1));
let t = tup!("", 2, 3.0);
let tup_pat!(a, b, c) = t;
assert_eq!(a, "");
assert_eq!(b, 2);
assert_eq!(c, tup!(3.0));
// don't match anything
let t = tup!(1, 2, 3, 4, 5);
let tup_pat!(..) = t;
let t = tup!(1, 2.0, "", vec![1], true);
let tup_pat!(a, b, c) = t;
assert_eq!(a, 1);
assert_eq!(b, 2.0);
assert_eq!(c, tup!("", vec![1], true)); // match the rest all
}
- get length of every tuple:
use tupley::prelude::*;
fn tuple_len() {
let t = tup!();
assert_eq!(0, t.len());
let t = tup!(1, false);
assert_eq!(2, t.len());
let t = tup!(1, 2, 3);
assert_eq!(3, t.len());
}
- add/combine two tuples into one (or pushing back/front new element)
use tupley::prelude::*;
fn tuple_add() {
let t1 = tup!(1, 2);
let t2 = tup!(3.0, false, Some(1));
let t = t1 + t2;
assert_eq!(t, tup!(1, 2, 3.0, false, Some(1)));
}
fn tuple_push() {
let t = tup!();
let t = t.push_back(1);
let t = t.push_back("str");
let t = t.push_back(false);
assert_eq!(t, tup!(1, "str", false));
let t = tup!();
let t = t.push_front(1);
let t = t.push_front("str");
let t = t.push_front(false);
assert_eq!(t, tup!(false, "str", 1));
}
- functor map
as_ref
/as_mut
/to_some
/to_ok
:
use tupley::prelude::*;
fn tuple_as_to() {
let t = tup!(1, "str", 3.0, false);
assert_eq!(t.as_ref(), tup!(&1, &"str", &3.0, &false));
let mut t = tup!(1, "str", 3.0, false);
assert_eq!(t.as_mut(), tup!(&mut 1, &mut "str", &mut 3.0, &mut false));
let t = tup!(1, "str", 3.0, false);
assert_eq!(t.to_some(), tup!(Some(1), Some("str"), Some(3.0), Some(false)));
let t = tup!(1, "str", 3.0, false);
assert_eq!(t.to_ok::<()>(), tup!(Ok(1), Ok("str"), Ok(3.0), Ok(false)));
}
- check length in compile-time for tuples passed in (using const generics):
Notice
: You should enable feature len-generic
switch toolchain into nightly
#![cfg_attr(feature = "len-generic", feature(generic_const_exprs))]
use tupley::prelude::*;
#[cfg(feature = "len-generic")]
fn tuple_len_generic() {
let t = tup!(1, 2, 3);
fn eq_yes<T: TupleLenEq<3>>(_: T) {}
eq_yes(t);
fn gt_yes<T: TupleLenGt<2>>(_: T) {}
gt_yes(t);
fn ge_yes_1<T: TupleLenGe<3>>(_: T) {}
ge_yes_1(t);
fn ge_yes_2<T: TupleLenGe<2>>(_: T) {}
ge_yes_2(t);
// LEN >= 3, LEN < 4
fn range_yes<T: TupleLenRange<3, 4>>(_: T) {}
range_yes(t);
// The following will failed in compile time
//
//
// fn ge_err<T: TupleLenGe<4>>(_: T) {}
// ge_err(t);
//
//
// fn gt_err<T: TupleLenGt<4>>(_: T) {}
// gt_err(t);
//
//
// fn eq_err<T: TupleLenEq<2>>(_: T) {}
// eq_err(t);
}
More work WIP.