fp_library/classes/par_ref_functor.rs
1//! Parallel by-reference functor mapping.
2//!
3//! **User story:** "I want to map over a collection by reference in parallel."
4//!
5//! This trait combines the by-reference access of [`RefFunctor`](crate::classes::RefFunctor) with
6//! the parallelism of [`ParFunctor`](crate::classes::ParFunctor). The closure receives `&A`
7//! (no consumption of elements) and must be `Send + Sync`. Elements must be `Send + Sync`
8//! for rayon's `par_iter()`.
9//!
10//! ### Examples
11//!
12//! ```
13//! use fp_library::{
14//! brands::VecBrand,
15//! classes::par_ref_functor::ParRefFunctor,
16//! };
17//!
18//! let v = vec![1, 2, 3];
19//! let result = VecBrand::par_ref_map(|x: &i32| x.to_string(), &v);
20//! assert_eq!(result, vec!["1", "2", "3"]);
21//! ```
22
23#[fp_macros::document_module]
24mod inner {
25 use {
26 crate::kinds::*,
27 fp_macros::*,
28 };
29
30 /// Parallel by-reference functor mapping.
31 ///
32 /// Maps a `Send + Sync` function over a structure by reference, potentially
33 /// using rayon for parallel execution. The closure receives `&A` instead
34 /// of consuming `A`.
35 ///
36 /// Elements must be `Send + Sync` because rayon's `par_iter()` requires
37 /// `&A: Send`, which is equivalent to `A: Sync`.
38 #[kind(type Of<'a, A: 'a>: 'a;)]
39 pub trait ParRefFunctor: crate::classes::RefFunctor {
40 /// Maps a function over the structure by reference in parallel.
41 #[document_signature]
42 #[document_type_parameters(
43 "The lifetime of the elements.",
44 "The input element type.",
45 "The output element type."
46 )]
47 #[document_parameters(
48 "The function to apply to each element reference. Must be `Send + Sync`.",
49 "The structure to map over."
50 )]
51 #[document_returns("A new structure containing the mapped elements.")]
52 #[document_examples]
53 ///
54 /// ```
55 /// use fp_library::{
56 /// brands::VecBrand,
57 /// classes::par_ref_functor::ParRefFunctor,
58 /// };
59 ///
60 /// let v = vec![1, 2, 3];
61 /// let result = VecBrand::par_ref_map(|x: &i32| x * 2, &v);
62 /// assert_eq!(result, vec![2, 4, 6]);
63 /// ```
64 fn par_ref_map<'a, A: Send + Sync + 'a, B: Send + 'a>(
65 f: impl Fn(&A) -> B + Send + Sync + 'a,
66 fa: &Self::Of<'a, A>,
67 ) -> Self::Of<'a, B>;
68 }
69
70 /// Maps a function over a structure by reference in parallel.
71 ///
72 /// Free function version that dispatches to [the type class' associated function][`ParRefFunctor::par_ref_map`].
73 #[document_signature]
74 #[document_type_parameters(
75 "The lifetime of the elements.",
76 "The brand of the structure.",
77 "The input element type.",
78 "The output element type."
79 )]
80 #[document_parameters(
81 "The function to apply to each element reference. Must be `Send + Sync`.",
82 "The structure to map over."
83 )]
84 #[document_returns("A new structure containing the mapped elements.")]
85 #[document_examples]
86 ///
87 /// ```
88 /// use fp_library::{
89 /// brands::VecBrand,
90 /// functions::*,
91 /// };
92 ///
93 /// let v = vec![1, 2, 3];
94 /// let result = par_ref_map::<VecBrand, _, _>(|x: &i32| x * 2, &v);
95 /// assert_eq!(result, vec![2, 4, 6]);
96 /// ```
97 pub fn par_ref_map<'a, Brand: ParRefFunctor, A: Send + Sync + 'a, B: Send + 'a>(
98 f: impl Fn(&A) -> B + Send + Sync + 'a,
99 fa: &Brand::Of<'a, A>,
100 ) -> Brand::Of<'a, B> {
101 Brand::par_ref_map(f, fa)
102 }
103}
104
105pub use inner::*;