Skip to main content

fp_library/classes/
send_ref_functor_with_index.rs

1//! Thread-safe by-reference variant of [`FunctorWithIndex`](crate::classes::FunctorWithIndex).
2//!
3//! **User story:** "I want to map over a thread-safe memoized value by reference, with access to the index."
4//!
5//! ### Examples
6//!
7//! ```
8//! use fp_library::{
9//! 	brands::*,
10//! 	classes::send_ref_functor_with_index::SendRefFunctorWithIndex,
11//! 	types::*,
12//! };
13//!
14//! let lazy = ArcLazy::new(|| 42);
15//! let mapped = <LazyBrand<ArcLazyConfig> as SendRefFunctorWithIndex>::send_ref_map_with_index(
16//! 	|_, x: &i32| x.to_string(),
17//! 	&lazy,
18//! );
19//! assert_eq!(*mapped.evaluate(), "42");
20//! ```
21
22#[fp_macros::document_module]
23mod inner {
24	use {
25		crate::{
26			classes::*,
27			kinds::*,
28		},
29		fp_macros::*,
30	};
31
32	/// Thread-safe by-reference mapping with index over a structure.
33	///
34	/// Similar to [`RefFunctorWithIndex`], but closures and elements must be `Send + Sync`.
35	#[kind(type Of<'a, A: 'a>: 'a;)]
36	pub trait SendRefFunctorWithIndex: SendRefFunctor + WithIndex {
37		/// Maps a function over the structure by reference with index (thread-safe).
38		#[document_signature]
39		#[document_type_parameters(
40			"The lifetime of the values.",
41			"The type of the elements.",
42			"The type of the result."
43		)]
44		#[document_parameters(
45			"The function to apply to each element's index and reference. Must be `Send + Sync`.",
46			"The structure to map over."
47		)]
48		#[document_returns("The mapped structure.")]
49		#[document_examples]
50		///
51		/// ```
52		/// use fp_library::{
53		/// 	brands::*,
54		/// 	classes::send_ref_functor_with_index::SendRefFunctorWithIndex,
55		/// 	types::*,
56		/// };
57		///
58		/// let lazy = ArcLazy::new(|| 42);
59		/// let mapped = <LazyBrand<ArcLazyConfig> as SendRefFunctorWithIndex>::send_ref_map_with_index(
60		/// 	|_, x: &i32| x.to_string(),
61		/// 	&lazy,
62		/// );
63		/// assert_eq!(*mapped.evaluate(), "42");
64		/// ```
65		fn send_ref_map_with_index<'a, A: Send + Sync + 'a, B: Send + Sync + 'a>(
66			f: impl Fn(Self::Index, &A) -> B + Send + Sync + 'a,
67			fa: &Self::Of<'a, A>,
68		) -> Self::Of<'a, B>;
69	}
70
71	/// Maps a function over a structure by reference with index (thread-safe).
72	///
73	/// Free function version that dispatches to [the type class' associated function][`SendRefFunctorWithIndex::send_ref_map_with_index`].
74	#[document_signature]
75	#[document_type_parameters(
76		"The lifetime of the values.",
77		"The brand of the structure.",
78		"The type of the elements.",
79		"The type of the result."
80	)]
81	#[document_parameters(
82		"The function to apply to each element's index and reference.",
83		"The structure to map over."
84	)]
85	#[document_returns("The mapped structure.")]
86	#[document_examples]
87	///
88	/// ```
89	/// use fp_library::{
90	/// 	brands::*,
91	/// 	functions::*,
92	/// 	types::*,
93	/// };
94	///
95	/// let lazy = ArcLazy::new(|| 42);
96	/// let mapped = send_ref_map_with_index::<LazyBrand<ArcLazyConfig>, _, _>(
97	/// 	|_, x: &i32| x.to_string(),
98	/// 	&lazy,
99	/// );
100	/// assert_eq!(*mapped.evaluate(), "42");
101	/// ```
102	pub fn send_ref_map_with_index<
103		'a,
104		Brand: SendRefFunctorWithIndex,
105		A: Send + Sync + 'a,
106		B: Send + Sync + 'a,
107	>(
108		f: impl Fn(Brand::Index, &A) -> B + Send + Sync + 'a,
109		fa: &Brand::Of<'a, A>,
110	) -> Brand::Of<'a, B> {
111		Brand::send_ref_map_with_index(f, fa)
112	}
113}
114
115pub use inner::*;