Skip to main content

fp_library/classes/
send_ref_apply_first.rs

1//! Thread-safe combining of two by-ref contexts, keeping the first value, with [`send_ref_apply_first`].
2//!
3//! This is the thread-safe counterpart of [`RefApplyFirst`](crate::classes::RefApplyFirst).
4//!
5//! ### Examples
6//!
7//! ```
8//! use fp_library::{
9//! 	brands::*,
10//! 	functions::*,
11//! 	types::*,
12//! };
13//!
14//! let x = ArcLazy::new(|| 3);
15//! let y = ArcLazy::new(|| 4);
16//! let result = send_ref_apply_first::<LazyBrand<ArcLazyConfig>, _, _>(&x, &y);
17//! assert_eq!(*result.evaluate(), 3);
18//! ```
19
20#[fp_macros::document_module]
21mod inner {
22	use {
23		crate::kinds::*,
24		fp_macros::*,
25	};
26
27	/// A type class for combining two thread-safe by-ref contexts, keeping the first value.
28	///
29	/// Requires `A: Clone + Send + Sync` because the closure receives `&A` and must produce
30	/// an owned `A`. The default implementation uses [`SendRefLift::send_ref_lift2`](crate::classes::SendRefLift::send_ref_lift2).
31	#[kind(type Of<'a, A: 'a>: 'a;)]
32	pub trait SendRefApplyFirst: crate::classes::SendRefLift {
33		/// Combines two contexts, keeping the value from the first.
34		#[document_signature]
35		///
36		#[document_type_parameters(
37			"The lifetime of the values.",
38			"The type of the value in the first context. Must be `Clone + Send + Sync`.",
39			"The type of the value in the second context."
40		)]
41		///
42		#[document_parameters("The first context.", "The second context.")]
43		///
44		#[document_returns("A new context containing the value from the first context.")]
45		#[document_examples]
46		///
47		/// ```
48		/// use fp_library::{
49		/// 	brands::*,
50		/// 	classes::*,
51		/// 	types::*,
52		/// };
53		///
54		/// let x = ArcLazy::new(|| 3);
55		/// let y = ArcLazy::new(|| 4);
56		/// let result = LazyBrand::<ArcLazyConfig>::send_ref_apply_first(&x, &y);
57		/// assert_eq!(*result.evaluate(), 3);
58		/// ```
59		fn send_ref_apply_first<'a, A: Clone + Send + Sync + 'a, B: Send + Sync + 'a>(
60			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
61			fb: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
62		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
63			Self::send_ref_lift2(|a: &A, _: &B| a.clone(), fa, fb)
64		}
65	}
66
67	/// Blanket implementation of [`SendRefApplyFirst`].
68	#[document_type_parameters("The brand type.")]
69	impl<Brand: crate::classes::SendRefLift> SendRefApplyFirst for Brand {}
70
71	/// Combines two thread-safe contexts, keeping the value from the first.
72	///
73	/// Free function version that dispatches to [the type class' associated function][`SendRefApplyFirst::send_ref_apply_first`].
74	#[document_signature]
75	///
76	#[document_type_parameters(
77		"The lifetime of the values.",
78		"The brand of the context.",
79		"The type of the value in the first context. Must be `Clone + Send + Sync`.",
80		"The type of the value in the second context."
81	)]
82	///
83	#[document_parameters("The first context.", "The second context.")]
84	///
85	#[document_returns("A new context containing the value from the first context.")]
86	#[document_examples]
87	///
88	/// ```
89	/// use fp_library::{
90	/// 	brands::*,
91	/// 	functions::*,
92	/// 	types::*,
93	/// };
94	///
95	/// let x = ArcLazy::new(|| 3);
96	/// let y = ArcLazy::new(|| 4);
97	/// let result = send_ref_apply_first::<LazyBrand<ArcLazyConfig>, _, _>(&x, &y);
98	/// assert_eq!(*result.evaluate(), 3);
99	/// ```
100	pub fn send_ref_apply_first<
101		'a,
102		Brand: SendRefApplyFirst,
103		A: Clone + Send + Sync + 'a,
104		B: Send + Sync + 'a,
105	>(
106		fa: &Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
107		fb: &Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
108	) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
109		Brand::send_ref_apply_first(fa, fb)
110	}
111}
112
113pub use inner::*;