1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//! Cloneable wrappers over closures for generic handling of functions in higher-kinded contexts.
//!
//! ### Examples
//!
//! ```
//! use fp_library::{
//! brands::*,
//! functions::*,
//! };
//!
//! let f = cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
//! assert_eq!(f(5), 10);
//! ```
#[fp_macros::document_module]
mod inner {
use {
crate::classes::*,
fp_macros::*,
std::ops::Deref,
};
/// A trait for cloneable wrappers over closures, allowing for generic handling of cloneable functions in higher-kinded contexts.
///
/// This trait is implemented by "Brand" types (like [`ArcFnBrand`][crate::brands::ArcFnBrand]
/// and [`RcFnBrand`][crate::brands::RcFnBrand]) to provide a way to construct
/// and type-check cloneable wrappers over closures (`Arc<dyn Fn...>` or
/// `Rc<dyn Fn...>`) in a generic context, allowing library users to choose
/// between implementations at function call sites.
///
/// The lifetime `'a` ensures the function doesn't outlive referenced data,
/// while generic types `A` and `B` represent the input and output types, respectively.
pub trait CloneableFn: Function {
/// The pointer brand backing this function wrapper.
///
/// Each `CloneableFn` implementor is backed by exactly one reference-counted
/// pointer type. For [`FnBrand<P>`](crate::brands::FnBrand), this is `P`.
type PointerBrand: RefCountedPointer;
/// The type of the cloneable function wrapper.
///
/// This associated type represents the concrete type of the wrapper (e.g., `Rc<dyn Fn(A) -> B>`)
/// that implements `Clone` and dereferences to the underlying closure.
type Of<'a, A: 'a, B: 'a>: 'a + Clone + Deref<Target = dyn 'a + Fn(A) -> B>;
/// Creates a new cloneable function wrapper.
///
/// This function wraps the provided closure `f` into a cloneable function.
#[document_signature]
///
#[document_type_parameters(
"The lifetime of the function and its captured data.",
"The input type of the function.",
"The output type of the function."
)]
///
#[document_parameters("The closure to wrap.", "The input value to the function.")]
#[document_returns("The wrapped cloneable function.")]
#[document_examples]
///
/// ```
/// use fp_library::{
/// brands::*,
/// functions::*,
/// };
///
/// let f = cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
/// assert_eq!(f(5), 10);
/// ```
fn new<'a, A: 'a, B: 'a>(f: impl 'a + Fn(A) -> B) -> <Self as CloneableFn>::Of<'a, A, B>;
}
/// Creates a new cloneable function wrapper.
///
/// Free function version that dispatches to [the type class' associated function][`CloneableFn::new`].
#[document_signature]
///
#[document_type_parameters(
"The lifetime of the function and its captured data.",
"The brand of the cloneable function wrapper.",
"The input type of the function.",
"The output type of the function."
)]
///
#[document_parameters("The closure to wrap.", "The input value to the function.")]
#[document_returns("The wrapped cloneable function.")]
#[document_examples]
///
/// ```
/// use fp_library::{
/// brands::*,
/// functions::*,
/// };
///
/// let f = cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2);
/// assert_eq!(f(5), 10);
/// ```
pub fn new<'a, Brand, A, B>(f: impl 'a + Fn(A) -> B) -> <Brand as CloneableFn>::Of<'a, A, B>
where
Brand: CloneableFn, {
<Brand as CloneableFn>::new(f)
}
}
pub use inner::*;