Skip to content

Instantly share code, notes, and snippets.

@pnkfelix
Created March 21, 2019 12:25
Show Gist options
  • Save pnkfelix/80fe57277434ef31f018c08fa8e21f84 to your computer and use it in GitHub Desktop.
Save pnkfelix/80fe57277434ef31f018c08fa8e21f84 to your computer and use it in GitHub Desktop.
#![allow(non_snake_case)]
#![feature(test)]
extern crate test;
use std::iter::FromIterator;
#[cfg(test)]
use test::Bencher;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
struct LastOne<T>(Option<T>);
impl<T> FromIterator<T> for LastOne<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> LastOne<T> {
LastOne(iter.into_iter().last())
}
}
type Last<T> = LastOne<T>;
impl<T> Last<T> {
fn new(x: T) -> Last<T> { LastOne(Some(x)) }
}
fn from_iter_baseline<C, T, E, I>(iter: I) -> Result<C, E>
where I: Iterator<Item = Result<T, E>>,
C: FromIterator<T>,
{
FromIterator::from_iter(iter)
}
fn from_iter_adapter<C, T, E, I>(iter: I) -> Result<C, E>
where I: Iterator<Item = Result<T, E>>,
C: FromIterator<T>,
{
struct Adapter<Iter, E> {
iter: Iter,
err: Option<E>,
}
impl<T, E, Iter: Iterator<Item=Result<T, E>>> Iterator for Adapter<Iter, E> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
match self.iter.next() {
Some(Ok(value)) => Some(value),
Some(Err(err)) => {
self.err = Some(err);
None
}
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_min, max) = self.iter.size_hint();
(0, max)
}
}
let mut adapter = Adapter { iter: iter, err: None };
let v: C = FromIterator::from_iter(adapter.by_ref());
match adapter.err {
Some(err) => Err(err),
None => Ok(v),
}
}
fn from_iter_with_scan_with_freevar<C, T, E, I>(iter: I) -> Result<C, E>
where I: Iterator<Item = Result<T, E>>,
C: FromIterator<T>,
{
let mut err = None;
let v = {
let adapter = iter.scan((), |_, item| {
match item {
Ok(x) => Some(x),
Err(x) => {
err = Some(x);
None
},
}
});
FromIterator::from_iter(adapter)
};
match err {
Some(err) => Err(err),
None => Ok(v),
}
}
fn from_iter_with_scan_passing_state<C, T, E, I>(iter: I) -> Result<C, E>
where I: Iterator<Item = Result<T, E>>,
C: FromIterator<T>,
{
let mut err = None;
let v = {
let adapter = iter.scan(&mut err, |err, item| {
match item {
Ok(x) => Some(x),
Err(x) => {
**err = Some(x);
None
},
}
});
FromIterator::from_iter(adapter)
};
match err {
Some(err) => Err(err),
None => Ok(v),
}
}
fn from_iter_with_filter_map<C, T, E, I>(iter: I) -> Result<C, E>
where I: Iterator<Item = Result<T, E>>,
C: FromIterator<T>,
{
let mut err = None;
let v = {
let adapter = iter.filter_map(|item| {
match item {
Ok(x) => Some(x),
Err(x) => {
err = Some(x);
None
},
}
});
FromIterator::from_iter(adapter)
};
match err {
Some(err) => Err(err),
None => Ok(v),
}
}
fn main() {
let one_a: Result<Last<u8>, _> = from_iter_baseline("1,2,3".split(",").map(|x| x.parse()));
let one_b: Result<Last<u8>, _> = from_iter_adapter("1,2,3".split(",").map(|x| x.parse()));
let two_a: Result<Last<u8>, _> = from_iter_with_scan_passing_state("1,2,3".split(",").map(|x| x.parse()));
let two_b: Result<Last<u8>, _> = from_iter_with_scan_with_freevar("1,2,3".split(",").map(|x| x.parse()));
let three: Result<Last<u8>, _> = from_iter_with_filter_map("1,2,3".split(",").map(|x| x.parse()));
println!("{:?}", one_a);
println!("{:?}", one_b);
println!("{:?}", two_a);
println!("{:?}", two_b);
println!("{:?}", three);
let one_a: Result<Last<u8>, _> = from_iter_baseline("1,a,3".split(",").map(|x| x.parse()));
let one_b: Result<Last<u8>, _> = from_iter_adapter("1,a,3".split(",").map(|x| x.parse()));
let two_a: Result<Last<u8>, _> = from_iter_with_scan_passing_state("1,a,3".split(",").map(|x| x.parse()));
let two_b: Result<Last<u8>, _> = from_iter_with_scan_with_freevar("1,a,3".split(",").map(|x| x.parse()));
let three: Result<Last<u8>, _> = from_iter_with_filter_map("1,a,3".split(",").map(|x| x.parse()));
println!("{:?}", one_a);
println!("{:?}", one_b);
println!("{:?}", two_a);
println!("{:?}", two_b);
println!("{:?}", three);
}
#[bench]
fn bench__vec_from_iter_using_baseline___(b: &mut Bencher) {
let expected = vec![1; 1000];
let v: Vec<Result<isize, String>> = vec![Ok(1); 1000];
b.iter(|| {
let result: Result<Vec<isize>, String> = from_iter_baseline(v.iter().cloned());
assert_eq!(result.unwrap(), expected);
});
}
#[bench]
fn bench__vec_from_iter_using_adapter____(b: &mut Bencher) {
let expected = vec![1; 1000];
let v: Vec<Result<isize, String>> = vec![Ok(1); 1000];
b.iter(|| {
let result: Result<Vec<isize>, String> = from_iter_adapter(v.iter().cloned());
assert_eq!(result.unwrap(), expected);
});
}
#[bench]
fn bench__vec_from_iter_with_scan_param__(b: &mut Bencher) {
let expected = vec![1; 1000];
let v: Vec<Result<isize, String>> = vec![Ok(1); 1000];
b.iter(|| {
let result: Result<Vec<isize>, String> = from_iter_with_scan_passing_state(v.iter().cloned());
assert_eq!(result.unwrap(), expected);
});
}
#[bench]
fn bench__vec_from_iter_with_scan_freevar(b: &mut Bencher) {
let expected = vec![1; 1000];
let v: Vec<Result<isize, String>> = vec![Ok(1); 1000];
b.iter(|| {
let result: Result<Vec<isize>, String> = from_iter_with_scan_with_freevar(v.iter().cloned());
assert_eq!(result.unwrap(), expected);
});
}
#[bench]
fn bench__vec_from_iter_with_filter_map__(b: &mut Bencher) {
let expected = vec![1; 1000];
let v: Vec<Result<isize, String>> = vec![Ok(1); 1000];
b.iter(|| {
let result: Result<Vec<isize>, String> = from_iter_with_filter_map(v.iter().cloned());
assert_eq!(result.unwrap(), expected);
});
}
#[bench]
fn bench_last_from_iter_using_baseline___(b: &mut Bencher) {
let expected = Last::new(1);
let v: Vec<Result<isize, String>> = vec![Ok(1); 3000];
b.iter(|| {
let result: Result<Last<isize>, String> = from_iter_baseline(v.iter().cloned());
assert_eq!(result.unwrap(), expected);
});
}
#[bench]
fn bench_last_from_iter_using_adapter____(b: &mut Bencher) {
let expected = Last::new(1);
let v: Vec<Result<isize, String>> = vec![Ok(1); 3000];
b.iter(|| {
let result: Result<Last<isize>, String> = from_iter_adapter(v.iter().cloned());
assert_eq!(result.unwrap(), expected);
});
}
#[bench]
fn bench_last_from_iter_with_scan_param__(b: &mut Bencher) {
let expected = Last::new(1);
let v: Vec<Result<isize, String>> = vec![Ok(1); 3000];
b.iter(|| {
let result: Result<Last<isize>, String> = from_iter_with_scan_passing_state(v.iter().cloned());
assert_eq!(result.unwrap(), expected);
});
}
#[bench]
fn bench_last_from_iter_with_scan_freevar(b: &mut Bencher) {
let expected = Last::new(1);
let v: Vec<Result<isize, String>> = vec![Ok(1); 3000];
b.iter(|| {
let result: Result<Last<isize>, String> = from_iter_with_scan_with_freevar(v.iter().cloned());
assert_eq!(result.unwrap(), expected);
});
}
#[bench]
fn bench_last_from_iter_with_filter_map__(b: &mut Bencher) {
let expected = Last::new(1);
let v: Vec<Result<isize, String>> = vec![Ok(1); 3000];
b.iter(|| {
let result: Result<Last<isize>, String> = from_iter_with_filter_map(v.iter().cloned());
assert_eq!(result.unwrap(), expected);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment