Skip to main content

fp_library/classes/
send_ref_apply_second.rs

1//! Thread-safe combining of two by-ref contexts, keeping the second value, with [`send_ref_apply_second`].
2//!
3//! This is the thread-safe counterpart of [`RefApplySecond`](crate::classes::RefApplySecond).
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_second::<LazyBrand<ArcLazyConfig>, _, _>(&x, &y);
17//! assert_eq!(*result.evaluate(), 4);
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 second value.
28	///
29	/// Requires `B: Clone + Send + Sync` because the closure receives `&B` and must produce
30	/// an owned `B`. 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 SendRefApplySecond: crate::classes::SendRefLift {
33		/// Combines two contexts, keeping the value from the second.
34		#[document_signature]
35		///
36		#[document_type_parameters(
37			"The lifetime of the values.",
38			"The type of the value in the first context.",
39			"The type of the value in the second context. Must be `Clone + Send + Sync`."
40		)]
41		///
42		#[document_parameters("The first context.", "The second context.")]
43		///
44		#[document_returns("A new context containing the value from the second 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_second(&x, &y);
57		/// assert_eq!(*result.evaluate(), 4);
58		/// ```
59		fn send_ref_apply_second<'a, A: Send + Sync + 'a, B: Clone + 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, B>) {
63			Self::send_ref_lift2(|_: &A, b: &B| b.clone(), fa, fb)
64		}
65	}
66
67	/// Blanket implementation of [`SendRefApplySecond`].
68	#[document_type_parameters("The brand type.")]
69	impl<Brand: crate::classes::SendRefLift> SendRefApplySecond for Brand {}
70
71	/// Combines two thread-safe contexts, keeping the value from the second.
72	///
73	/// Free function version that dispatches to [the type class' associated function][`SendRefApplySecond::send_ref_apply_second`].
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.",
80		"The type of the value in the second context. Must be `Clone + Send + Sync`."
81	)]
82	///
83	#[document_parameters("The first context.", "The second context.")]
84	///
85	#[document_returns("A new context containing the value from the second 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_second::<LazyBrand<ArcLazyConfig>, _, _>(&x, &y);
98	/// assert_eq!(*result.evaluate(), 4);
99	/// ```
100	pub fn send_ref_apply_second<
101		'a,
102		Brand: SendRefApplySecond,
103		A: Send + Sync + 'a,
104		B: Clone + 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, B>) {
109		Brand::send_ref_apply_second(fa, fb)
110	}
111}
112
113pub use inner::*;