#![recursion_limit = "128"] #[macro_use] extern crate generic_array; use generic_array::typenum::consts::U4; use std::fmt::Debug; use std::ops::Add; use generic_array::{GenericArray, ArrayLength}; use generic_array::sequence::*; use generic_array::functional::*; /// Example function using generics to pass N-length sequences and map them pub fn generic_map(s: S) where S: FunctionalSequence, // `.map` S::Item: Add, // `x + 1` S: MappedGenericSequence, // `i32` -> `i32` MappedSequence: Debug, // println! { let a = s.map(|x| x + 1); println!("{:?}", a); } /// Complex example function using generics to pass N-length sequences, zip them, and then map that result. /// /// If used with `GenericArray` specifically this isn't necessary pub fn generic_sequence_zip_sum(a: A, b: B) -> i32 where A: FunctionalSequence, // `.zip` B: FunctionalSequence, // `.zip` A: MappedGenericSequence, // `i32` -> `i32` B: MappedGenericSequence>, // `i32` -> `i32`, prove A and B can map to the same output A::Item: Add, // `l + r` MappedSequence: MappedGenericSequence + FunctionalSequence, // `.map` SequenceItem>: Add, // `x + 1` MappedSequence, i32, i32>: Debug, // `println!` MappedSequence, i32, i32>: FunctionalSequence, // `.fold` SequenceItem, i32, i32>>: Add // `x + a`, note the order { let c = a.zip(b, |l, r| l + r).map(|x| x + 1); println!("{:?}", c); c.fold(0, |a, x| x + a) } /// Super-simple fixed-length i32 `GenericArray`s pub fn generic_array_plain_zip_sum(a: GenericArray, b: GenericArray) -> i32 { a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a) } pub fn generic_array_variable_length_zip_sum(a: GenericArray, b: GenericArray) -> i32 where N: ArrayLength, { a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a) } pub fn generic_array_same_type_variable_length_zip_sum(a: GenericArray, b: GenericArray) -> i32 where N: ArrayLength + ArrayLength<>::Output>, T: Add, { a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a) } /// Complex example using fully generic `GenericArray`s with the same length. /// /// It's mostly just the repeated `Add` traits, which would be present in other systems anyway. pub fn generic_array_zip_sum + ArrayLength>(a: GenericArray, b: GenericArray) -> i32 where A: Add, N: ArrayLength<>::Output> + ArrayLength<<>::Output as Add>::Output>, >::Output: Add, <>::Output as Add>::Output: Add, { a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a) } #[test] fn test_generics() { generic_map(arr![i32; 1, 2, 3, 4]); assert_eq!(generic_sequence_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28); assert_eq!(generic_array_plain_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28); assert_eq!(generic_array_variable_length_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28); assert_eq!(generic_array_same_type_variable_length_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28); assert_eq!(generic_array_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28); }