Skip to content

Commit

Permalink
Hide MapFolder
Browse files Browse the repository at this point in the history
map_collect_fold_reduce_into_vec is now
map_collect_fold_reduce_into_vec_with, and it takes an
initial value, a mapfold function and a reduce function.
  • Loading branch information
nox committed Apr 4, 2019
1 parent e58ea05 commit 099ec2e
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 70 deletions.
1 change: 1 addition & 0 deletions src/iter/collect/consumer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::super::noop::*;
use super::super::plumbing::*;
use super::MapFolder;
use std::marker::PhantomData;
use std::ptr;
use std::slice;
Expand Down
90 changes: 84 additions & 6 deletions src/iter/collect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,90 @@ use super::unzip::unzip_indexed;

mod test;

/// Collects the results of the exact iterator into the specified vector
/// and fold-reduce over references to the items of that vector.
///
/// The `MapFolder` trait represents a "map fold" operation, where the "map"
/// part is encoded by the `consume` method taking `Self::Item` and returning
/// `T`, and where the "fold" part is encoded by `map` taking `&mut self` and
/// the `complete` method returning `Self::Result`.
pub trait MapFolder<Item>: Sized {
/// The output returned when consuming an item.
type Output: Send;

/// The type of result that will ultimately be produced by the map folder.
type Result: Send;

/// Consume an item.
fn consume(self, item: Item) -> (Self, Self::Output);

/// Finish consuming items, produce final result.
fn complete(self) -> Self::Result;
}

/// This is not directly public, but called by
/// `IndexedParallelIterator::collect_into_vec_and_fold_reduce`.
pub fn map_collect_fold_reduce_into_vec_with<'c, I, T, F, R>(
/// `IndexedParallelIterator::map_collect_fold_reduce_into_vec_with`.
pub fn map_collect_fold_reduce_into_vec_with<'c, I, T, U, F, R>(
pi: I,
v: &'c mut Vec<T>,
init: U,
mapfold_op: F,
reduce_op: R,
) -> U
where
I: IndexedParallelIterator,
T: Send + 'c,
U: Clone + Send,
F: Fn(U, I::Item) -> (U, T) + Sync + Send,
R: Fn(U, U) -> U + Sync + Send,
{
#[derive(Clone)]
struct MapFoldCallback<U, F> {
result: U,
mapfold_op: F,
}

impl<'a, I, T, U, F> MapFolder<I> for MapFoldCallback<U, F>
where
T: Send,
U: Send,
F: Fn(U, I) -> (U, T) + Send,
{
type Output = T;
type Result = U;

fn consume(self, item: I) -> (Self, Self::Output) {
let MapFoldCallback { result, mapfold_op } = self;
let (result, output) = mapfold_op(result, item);
(MapFoldCallback { result, mapfold_op }, output)
}

fn complete(self) -> Self::Result {
self.result
}
}

#[derive(Clone)]
struct ReducerCallback<R>(R);

impl<U, R> Reducer<U> for ReducerCallback<R>
where
R: FnOnce(U, U) -> U,
{
fn reduce(self, left: U, right: U) -> U {
(self.0)(left, right)
}
}

map_collect_fold_reduce_into_vec(
pi,
v,
MapFoldCallback {
result: init,
mapfold_op: &mapfold_op,
},
ReducerCallback(&reduce_op),
)
}

fn map_collect_fold_reduce_into_vec<'c, I, T, F, R>(
pi: I,
v: &'c mut Vec<T>,
map_folder: F,
Expand All @@ -43,7 +121,7 @@ where
I: IndexedParallelIterator<Item = T>,
T: Send,
{
map_collect_fold_reduce_into_vec_with(pi, v, NoopConsumer, NoopReducer)
map_collect_fold_reduce_into_vec(pi, v, NoopConsumer, NoopReducer)
}

/// Collects the results of the iterator into the specified vector.
Expand Down
74 changes: 28 additions & 46 deletions src/iter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1984,63 +1984,45 @@ pub trait IndexedParallelIterator: ParallelIterator {
///
/// ```
/// use rayon::prelude::*;
/// use rayon::iter::plumbing::{MapFolder, Reducer};
///
/// // any prior data will be truncated
/// let mut vec = vec![1, 2, 3];
/// let mut vec: Vec<usize> = vec![1, 2, 3];
///
/// #[derive(Clone)]
/// struct NegativeFolder(Vec<isize>);
///
/// impl MapFolder<isize> for NegativeFolder {
/// type Output = usize;
/// type Result = Vec<isize>;
///
/// fn consume(mut self, item: isize) -> (Self, Self::Output) {
/// if item >= 0 {
/// (self, item as usize)
/// } else {
/// self.0.push(item);
/// (self, 0)
/// }
/// }
///
/// fn complete(self) -> Vec<isize> {
/// self.0
/// }
/// }
///
/// #[derive(Clone)]
/// struct NegativeReducer;
///
/// impl Reducer<Vec<isize>> for NegativeReducer {
/// fn reduce(self, mut left: Vec<isize>, mut right: Vec<isize>) -> Vec<isize> {
/// left.append(&mut right);
/// left
/// }
/// }
///
/// let negative_numbers =
/// let negative_numbers: Vec<isize> =
/// [4, -7, 18, 25, -9].par_iter().cloned().map_collect_fold_reduce_into_vec_with(
/// &mut vec,
/// NegativeFolder(vec![]),
/// NegativeReducer
/// vec![],
/// |mut result, item| {
/// if item >= 0 {
/// (result, item as usize)
/// } else {
/// result.push(item);
/// (result, 0)
/// }
/// },
/// |mut left, mut right| {
/// left.append(&mut right);
/// left
/// }
/// );
///
/// assert_eq!(vec, [4, 0, 18, 25, 0]);
/// assert_eq!(negative_numbers, [-7, -9]);
/// ```
fn map_collect_fold_reduce_into_vec_with<F, R>(
fn map_collect_fold_reduce_into_vec_with<'c, T, U, F, R>(
self,
target: &mut Vec<F::Output>,
map_folder: F,
reducer: R,
) -> F::Result
where
F: Clone + MapFolder<Self::Item> + Send,
R: Clone + Reducer<F::Result> + Send,
{
collect::map_collect_fold_reduce_into_vec_with(self, target, map_folder, reducer)
target: &mut Vec<T>,
init: U,
mapfold_op: F,
reduce_op: R,
) -> U
where
T: Send + 'c,
U: Clone + Send,
F: Fn(U, Self::Item) -> (U, T) + Sync + Send,
R: Fn(U, U) -> U + Sync + Send,
{
collect::map_collect_fold_reduce_into_vec_with(self, target, init, mapfold_op, reduce_op)
}

/// Unzips the results of the iterator into the specified
Expand Down
1 change: 1 addition & 0 deletions src/iter/noop.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::collect::MapFolder;
use super::plumbing::*;

#[derive(Clone)]
Expand Down
18 changes: 0 additions & 18 deletions src/iter/plumbing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,24 +192,6 @@ pub trait Folder<Item>: Sized {
fn full(&self) -> bool;
}

/// The `MapFolder` trait represents a "map fold" operation, where the "map"
/// part is encoded by the `consume` method taking `Self::Item` and returning
/// `T`, and where the "fold" part is encoded by `map` taking `&mut self` and
/// the `complete` method returning `Self::Result`.
pub trait MapFolder<Item>: Sized {
/// The output returned when consuming an item.
type Output: Send;

/// The type of result that will ultimately be produced by the map folder.
type Result: Send;

/// Consume an item.
fn consume(self, item: Item) -> (Self, Self::Output);

/// Finish consuming items, produce final result.
fn complete(self) -> Self::Result;
}

/// The reducer is the final step of a `Consumer` -- after a consumer
/// has been split into two parts, and each of those parts has been
/// fully processed, we are left with two results. The reducer is then
Expand Down

0 comments on commit 099ec2e

Please sign in to comment.