concision_core/traits/
apply.rs

1/*
2    appellation: apply <module>
3    authors: @FL03
4*/
5/// The [`CallInto`] trait is a consuming interface for passing an object into a single-valued
6/// function. While the intended affect is the same as [`CallOn`], the difference is that
7/// [`CallInto`] enables a transfer of ownership instead of relyin upon a reference.
8pub trait CallInto<T> {
9    type Output;
10
11    /// The `call_into` method allows an object to be passed into a function that takes ownership
12    /// of the object. This is useful for cases where you want to perform an operation on an
13    /// object and consume it in the process.
14    fn call_into<F>(self, f: F) -> Self::Output
15    where
16        F: FnOnce(T) -> Self::Output;
17}
18/// The [`CallOn`] trait enables an object to be passed onto a unary, or single value, function
19/// that is applied to the object.
20pub trait CallOn<T>: CallInto<T> {
21    /// The `call_on` method allows an object to be passed onto a function that takes a reference
22    /// to the object. This is useful for cases where you want to perform an operation on
23    /// an object without needing to extract it from a container or context.
24    fn call_on<F>(&self, f: F) -> Self::Output
25    where
26        F: FnMut(&T) -> Self::Output;
27}
28/// The [`CallOnMut`] is a supertrait of the [`CallInto`] trait that enables an object to be
29/// passed onto a unary, or single value, function that is applied to the object, but with the
30/// ability to mutate the object in-place.
31pub trait CallInPlace<T>: CallInto<T> {
32    /// The `call_on_mut` method allows an object to be passed onto a function that takes a mutable reference
33    /// to the object. This is useful for cases where you want to perform an operation on
34    /// an object and mutate it in the process.
35    fn call_inplace<F>(&mut self, f: F) -> Self::Output
36    where
37        F: FnMut(&mut T) -> Self::Output;
38}
39
40/// The [`Apply`] establishes an interface for _owned_ containers that are capable of applying
41/// some function onto their elements.
42pub trait Apply<T> {
43    type Cont<_T>;
44
45    fn apply<U, F>(&self, f: F) -> Self::Cont<U>
46    where
47        F: Fn(T) -> U;
48}
49/// The [`ApplyMut`] trait mutates the each element of the container, in-place, using the given
50/// function.
51pub trait ApplyMut<T> {
52    type Cont<_T>;
53
54    fn apply_mut<'a, F>(&'a mut self, f: F)
55    where
56        T: 'a,
57        F: FnMut(T) -> T;
58}
59
60/*
61 ************* Implementations *************
62*/
63use ndarray::{Array, ArrayBase, Data, DataMut, Dimension, ScalarOperand};
64use ndtensor::{Tensor, TensorBase};
65
66impl<T> CallInto<T> for T {
67    type Output = T;
68
69    fn call_into<F>(self, f: F) -> Self::Output
70    where
71        F: FnOnce(T) -> Self::Output,
72    {
73        f(self)
74    }
75}
76
77impl<T> CallOn<T> for T
78where
79    T: CallInto<T>,
80{
81    fn call_on<F>(&self, mut f: F) -> Self::Output
82    where
83        F: FnMut(&T) -> Self::Output,
84    {
85        f(self)
86    }
87}
88
89impl<T> CallInPlace<T> for T
90where
91    T: CallInto<T>,
92{
93    fn call_inplace<F>(&mut self, mut f: F) -> Self::Output
94    where
95        F: FnMut(&mut T) -> Self::Output,
96    {
97        f(self)
98    }
99}
100
101impl<A, S, D> Apply<A> for ArrayBase<S, D>
102where
103    A: ScalarOperand,
104    D: Dimension,
105    S: Data<Elem = A>,
106{
107    type Cont<V> = Array<V, D>;
108
109    fn apply<V, F>(&self, f: F) -> Self::Cont<V>
110    where
111        F: Fn(A) -> V,
112    {
113        self.mapv(f)
114    }
115}
116
117impl<A, S, D> Apply<A> for TensorBase<S, D>
118where
119    A: ScalarOperand,
120    D: Dimension,
121    S: Data<Elem = A>,
122{
123    type Cont<V> = Tensor<V, D>;
124
125    fn apply<V, F>(&self, f: F) -> Self::Cont<V>
126    where
127        F: Fn(A) -> V,
128    {
129        self.map(f)
130    }
131}
132
133impl<A, S, D> Apply<A> for &ArrayBase<S, D>
134where
135    A: ScalarOperand,
136    D: Dimension,
137    S: Data<Elem = A>,
138{
139    type Cont<V> = Array<V, D>;
140
141    fn apply<B, F>(&self, f: F) -> Array<B, D>
142    where
143        F: Fn(A) -> B,
144    {
145        self.mapv(f)
146    }
147}
148
149impl<A, S, D> Apply<A> for &mut ArrayBase<S, D>
150where
151    A: ScalarOperand,
152    D: Dimension,
153    S: Data<Elem = A>,
154{
155    type Cont<V> = Array<V, D>;
156
157    fn apply<B, F>(&self, f: F) -> Array<B, D>
158    where
159        F: Fn(A) -> B,
160    {
161        self.mapv(f)
162    }
163}
164
165impl<A, S, D> ApplyMut<A> for ArrayBase<S, D>
166where
167    A: ScalarOperand,
168    D: Dimension,
169    S: DataMut<Elem = A>,
170{
171    type Cont<V> = Array<V, D>;
172
173    fn apply_mut<'a, F>(&'a mut self, f: F)
174    where
175        A: 'a,
176        F: FnMut(A) -> A,
177    {
178        self.mapv_inplace(f)
179    }
180}
181
182impl<A, S, D> ApplyMut<A> for &mut ArrayBase<S, D>
183where
184    A: ScalarOperand,
185    D: Dimension,
186    S: DataMut<Elem = A>,
187{
188    type Cont<V> = Array<V, D>;
189
190    fn apply_mut<'b, F>(&'b mut self, f: F)
191    where
192        A: 'b,
193        F: FnMut(A) -> A,
194    {
195        self.mapv_inplace(f)
196    }
197}