fp_library/classes/par_compactable.rs
1//! Data structures that can be compacted and separated in parallel.
2//!
3//! ### Examples
4//!
5//! ```
6//! use fp_library::{
7//! brands::*,
8//! functions::*,
9//! };
10//!
11//! let v = vec![Some(1), None, Some(3)];
12//! let result: Vec<i32> = par_compact::<VecBrand, _>(v);
13//! assert_eq!(result, vec![1, 3]);
14//! ```
15
16#[fp_macros::document_module]
17mod inner {
18 use {
19 crate::{
20 brands::*,
21 kinds::*,
22 },
23 fp_macros::*,
24 };
25
26 /// A type class for data structures that can be compacted and separated in parallel.
27 ///
28 /// `ParCompactable` is the parallel counterpart to [`Compactable`](crate::classes::Compactable).
29 /// Implementors define [`par_compact`][ParCompactable::par_compact] and
30 /// [`par_separate`][ParCompactable::par_separate] directly: there is no intermediate `Vec`
31 /// conversion imposed by the interface.
32 ///
33 /// ### Thread Safety
34 ///
35 /// All `par_*` functions require `Send` bounds on element types.
36 /// These bounds apply even when the `rayon` feature is disabled, so that code compiles
37 /// identically in both configurations.
38 ///
39 /// **Note: The `rayon` feature must be enabled to use actual parallel execution. Without
40 /// it, all `par_*` functions fall back to equivalent sequential operations.**
41 #[document_examples]
42 ///
43 /// ```
44 /// use fp_library::{
45 /// brands::VecBrand,
46 /// functions::*,
47 /// };
48 ///
49 /// let v = vec![Some(1), None, Some(3)];
50 /// let result: Vec<i32> = par_compact::<VecBrand, _>(v);
51 /// assert_eq!(result, vec![1, 3]);
52 ///
53 /// let v2: Vec<Result<i32, &str>> = vec![Ok(1), Err("e"), Ok(3)];
54 /// let (errs, oks): (Vec<&str>, Vec<i32>) = par_separate::<VecBrand, _, _>(v2);
55 /// assert_eq!(errs, vec!["e"]);
56 /// assert_eq!(oks, vec![1, 3]);
57 /// ```
58 pub trait ParCompactable: Kind_cdc7cd43dac7585f {
59 /// Compacts a data structure of [`Option`]s in parallel, discarding [`None`] values and
60 /// keeping [`Some`] values.
61 ///
62 /// When the `rayon` feature is enabled, elements are processed across multiple threads.
63 /// Otherwise falls back to sequential compaction.
64 #[document_signature]
65 ///
66 #[document_type_parameters(
67 "The lifetime of the elements.",
68 "The type of the elements in the [`Option`]."
69 )]
70 ///
71 #[document_parameters("The data structure containing [`Option`] values.")]
72 ///
73 #[document_returns(
74 "A new data structure containing only the values from the [`Some`] variants."
75 )]
76 #[document_examples]
77 ///
78 /// ```
79 /// use fp_library::{
80 /// brands::VecBrand,
81 /// classes::par_compactable::ParCompactable,
82 /// };
83 ///
84 /// let v = vec![Some(1), None, Some(3)];
85 /// let result: Vec<i32> = VecBrand::par_compact(v);
86 /// assert_eq!(result, vec![1, 3]);
87 /// ```
88 fn par_compact<'a, A: 'a + Send>(
89 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
90 'a,
91 Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
92 >)
93 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>);
94
95 /// Separates a data structure of [`Result`]s into two data structures in parallel.
96 ///
97 /// When the `rayon` feature is enabled, elements are processed across multiple threads.
98 /// Otherwise falls back to sequential separation.
99 #[document_signature]
100 ///
101 #[document_type_parameters(
102 "The lifetime of the elements.",
103 "The type of the error values.",
104 "The type of the success values."
105 )]
106 ///
107 #[document_parameters("The data structure containing [`Result`] values.")]
108 ///
109 #[document_returns(
110 "A pair of data structures: the first containing the [`Err`] values, and the second containing the [`Ok`] values."
111 )]
112 #[document_examples]
113 ///
114 /// ```
115 /// use fp_library::{
116 /// brands::VecBrand,
117 /// classes::par_compactable::ParCompactable,
118 /// };
119 ///
120 /// let v: Vec<Result<i32, &str>> = vec![Ok(1), Err("e"), Ok(3)];
121 /// let (errs, oks): (Vec<&str>, Vec<i32>) = VecBrand::par_separate(v);
122 /// assert_eq!(errs, vec!["e"]);
123 /// assert_eq!(oks, vec![1, 3]);
124 /// ```
125 fn par_separate<'a, E: 'a + Send, O: 'a + Send>(
126 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
127 ) -> (
128 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
129 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
130 );
131 }
132
133 /// Compacts a data structure of [`Option`]s in parallel, discarding [`None`] values and
134 /// keeping [`Some`] values.
135 ///
136 /// Free function version that dispatches to [`ParCompactable::par_compact`].
137 #[document_signature]
138 ///
139 #[document_type_parameters(
140 "The lifetime of the elements.",
141 "The brand of the compactable structure.",
142 "The type of the elements in the [`Option`]."
143 )]
144 ///
145 #[document_parameters("The data structure containing [`Option`] values.")]
146 ///
147 #[document_returns(
148 "A new data structure containing only the values from the [`Some`] variants."
149 )]
150 #[document_examples]
151 ///
152 /// ```
153 /// use fp_library::{
154 /// brands::*,
155 /// functions::*,
156 /// };
157 ///
158 /// let v = vec![Some(1), None, Some(3)];
159 /// let result: Vec<i32> = par_compact::<VecBrand, _>(v);
160 /// assert_eq!(result, vec![1, 3]);
161 /// ```
162 pub fn par_compact<'a, Brand: ParCompactable, A: 'a + Send>(
163 fa: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
164 'a,
165 Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
166 >)
167 ) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
168 Brand::par_compact(fa)
169 }
170
171 /// Separates a data structure of [`Result`]s into two data structures in parallel.
172 ///
173 /// Free function version that dispatches to [`ParCompactable::par_separate`].
174 #[document_signature]
175 ///
176 #[document_type_parameters(
177 "The lifetime of the elements.",
178 "The brand of the compactable structure.",
179 "The type of the error values.",
180 "The type of the success values."
181 )]
182 ///
183 #[document_parameters("The data structure containing [`Result`] values.")]
184 ///
185 #[document_returns(
186 "A pair of data structures: the first containing the [`Err`] values, and the second containing the [`Ok`] values."
187 )]
188 #[document_examples]
189 ///
190 /// ```
191 /// use fp_library::{
192 /// brands::*,
193 /// functions::*,
194 /// };
195 ///
196 /// let v: Vec<Result<i32, &str>> = vec![Ok(1), Err("e"), Ok(3)];
197 /// let (errs, oks): (Vec<&str>, Vec<i32>) = par_separate::<VecBrand, _, _>(v);
198 /// assert_eq!(errs, vec!["e"]);
199 /// assert_eq!(oks, vec![1, 3]);
200 /// ```
201 pub fn par_separate<'a, Brand: ParCompactable, E: 'a + Send, O: 'a + Send>(
202 fa: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
203 ) -> (
204 Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
205 Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
206 ) {
207 Brand::par_separate::<E, O>(fa)
208 }
209}
210
211pub use inner::*;