Skip to main content

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::*;