Skip to content

Instantly share code, notes, and snippets.

@conundrumer
Created November 22, 2016 21:16
Show Gist options
  • Save conundrumer/4e57c14705055bb2deac1b9fde84f83b to your computer and use it in GitHub Desktop.
Save conundrumer/4e57c14705055bb2deac1b9fde84f83b to your computer and use it in GitHub Desktop.
returning iterators in rust
#![feature(conservative_impl_trait)]
// without impl trait or box
use std::iter::{ FlatMap, Map, Enumerate, Iterator };
use std::str::Chars;
type GetIterFnType = Fn((usize, char)) -> Option<char>;
type IdentityType = Fn(Option<char>) -> Option<char>;
type GetIterType<'a> = FlatMap<Map<Enumerate<Chars<'a>>, &'static GetIterFnType>, Option<char>, &'static IdentityType>;
const GET_ITER_FN: &'static GetIterFnType = &|(i, x)| if i % 2 == 0 { Some(x) } else { None };
const IDENTITY: &'static IdentityType = &|x| x;
fn get_iter<'a>() -> GetIterType<'a>{
"abcdefg".chars().enumerate().map(GET_ITER_FN).flat_map(IDENTITY)
}
// with impl trait
fn get_iter_impl<'a>() -> impl Iterator<Item=char> + 'a {
"abcdefg".chars().enumerate()
.map(|(i, x)| if i % 2 == 0 { Some(x) } else { None })
.flat_map(|x| x)
}
fn get_iter_env<'a>(s: &'a str, n: usize) -> impl Iterator<Item=char> + 'a {
s.chars().enumerate()
.map(move |(i, x)| if i % n == 0 { Some(x) } else { None })
.flat_map(|x| x)
}
fn get_iter_iter<'a>(n: usize) -> impl Iterator<Item=usize> + 'a {
(0..n).flat_map(|i| (0..i))
}
// recursive abstract iterators crash the compiler bc they never resolve to concrete types
// fn get_iter_recursive<'a>(n: usize) -> impl Iterator<Item=usize> + 'a {
// // can't combine two different kinds of iterators (even if they are anonymous)
// // match n {
// // 0 => (0..n),
// // _ => (0..n).flat_map(get_iter_recursive)
// // }
// (0..n).flat_map(get_iter_recursive)
// }
// must box iterators to make them recursive
fn get_iter_recursive_box(i: usize, n: usize) -> Box<Iterator<Item=usize>> {
if i == n {
return Box::new(0..n)
}
Box::new((0..n).flat_map(move |j| get_iter_recursive_box(j, n - 1)))
}
// non-iterator impl
fn vec_permutate<T>(vec: Vec<T>) -> Vec<Vec<T>> where T: Copy + Clone + 'static {
fn perm<U>(current: Vec<U>, remaining: Vec<U>) -> Vec<Vec<U>> where U: Copy + Clone + 'static {
if remaining.len() == 0 {
return vec![current]
}
remaining.iter().enumerate().flat_map(|(i, &x)| {
let mut remaining = remaining.clone();
remaining.remove(i);
let mut next = current.clone();
next.push(x);
perm(next, remaining)
}).collect()
}
perm(vec![], vec)
}
// iterator impl
fn iter_permutate<T>(vec: Vec<T>) -> Box<Iterator<Item=Vec<T>>> where T: Copy + Clone + 'static {
fn perm<U>(current: Vec<U>, remaining: Vec<U>) -> Box<Iterator<Item=Vec<U>>> where U: Copy + Clone + 'static {
if remaining.len() == 0 {
return Box::new(Some(current).into_iter())
}
Box::new(remaining.clone().into_iter().enumerate().flat_map(move |(i, x)| {
let mut remaining = remaining.clone();
remaining.remove(i);
let mut next = current.clone();
next.push(x);
perm(next, remaining)
}))
}
perm(vec![], vec)
}
fn main() {
let vec: Vec<_> = get_iter().collect();
let vec2: Vec<_> = get_iter_impl().collect();
let vec3: Vec<_> = get_iter_env("qwertyuiop", 3).collect();
let vec4: Vec<_> = get_iter_iter(5).collect();
println!("{:?},{:?},{:?},{:?}", vec, vec2, vec3, vec4);
let vec5: Vec<_> = get_iter_recursive_box(0, 4).collect();
println!("{:?}", vec5);
println!("{:?}", vec_permutate(vec![1,2,3]));
let vec6: Vec<_> = iter_permutate(vec![1,2,3]).collect();
println!("{:?}", vec6);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment