Skip to main content

core_extensions/
callable.rs

1//! Alternatives of the standard [`Fn`]/[`FnMut`]/[`FnOnce`] traits,
2//! implementable in stable Rust.
3//!
4//! [`Fn`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
5//!
6//! [`FnMut`]: https://doc.rust-lang.org/std/ops/trait.FnMut.html
7//!
8//! [`FnOnce`]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html
9
10
11
12#[cfg(test)]
13mod tests;
14
15
16
17/// Extension trait for calling `Call*` closures.
18pub trait CallExt {
19    /// For calling [`CallRef::ref_call_`],
20    /// with the ability to specify the types of the arguments..
21    ///
22    /// # Example
23    ///
24    /// ```rust
25    /// use core_extensions::{impl_call, CallExt};
26    ///
27    /// struct PushTwice;
28    ///
29    /// impl_call! { 
30    ///     fn ref_call[T](self: PushTwice, vector: &mut Vec<T>, value: T )
31    ///     where[ T: Clone ]
32    ///     {
33    ///         vector.push(value.clone());
34    ///         vector.push(value);
35    ///     }
36    /// }
37    ///
38    /// let mut vector = Vec::new();
39    ///
40    /// // `Call*` style closures encode multiple parameters as tuples
41    /// PushTwice.ref_call((&mut vector, 3));
42    /// assert_eq!(vector, [3, 3]);
43    ///
44    /// // The turbofish operator can be used to specify the types of the arguments.
45    /// PushTwice.ref_call::<(_, u128)>((&mut vector, 5));
46    /// assert_eq!(vector, [3, 3, 5, 5]);
47    ///
48    /// PushTwice.ref_call((&mut vector, 8));
49    /// assert_eq!(vector, [3, 3, 5, 5, 8, 8]);
50    ///
51    /// ```
52    /// 
53    /// [`CallRef::ref_call_`]: ./trait.CallRef.html#tymethod.ref_call_
54    #[inline(always)]
55    fn ref_call<P>(&self, params: P) -> Self::Returns
56    where
57        Self: CallRef<P>
58    {
59        self.ref_call_(params)
60    }
61
62    /// For calling [`CallMut::mut_call_`],
63    /// with the ability to specify the types of the arguments..
64    ///
65    /// # Example
66    /// 
67    /// ```rust
68    /// use core_extensions::{impl_call, CallExt};
69    ///
70    /// struct ComputeFib {
71    ///     nums: [u128; 2],
72    /// }
73    ///
74    /// impl_call! { 
75    ///     fn mut_call(self: ComputeFib, numbers: &mut Vec<u128>) {
76    ///         let [l, r] = self.nums;
77    ///         let next = l + r;
78    ///         self.nums = [r, next];
79    ///         numbers.push(r);
80    ///     }
81    /// }
82    ///
83    /// let mut fibs = ComputeFib {nums: [0, 1]};
84    /// 
85    /// let mut numbers = Vec::new();
86    ///
87    /// // The turbofish operator can be used to specify the types of the arguments.
88    /// fibs.mut_call::<&mut Vec<u128>>(&mut numbers);
89    /// assert_eq!(numbers, [1]);
90    ///
91    /// fibs.mut_call(&mut numbers);
92    /// assert_eq!(numbers, [1, 1]);
93    ///
94    /// fibs.mut_call(&mut numbers);
95    /// assert_eq!(numbers, [1, 1, 2]);
96    ///
97    /// fibs.mut_call(&mut numbers);
98    /// assert_eq!(numbers, [1, 1, 2, 3]);
99    ///
100    /// fibs.mut_call(&mut numbers);
101    /// assert_eq!(numbers, [1, 1, 2, 3, 5]);
102    ///
103    /// fibs.mut_call(&mut numbers);
104    /// assert_eq!(numbers, [1, 1, 2, 3, 5, 8]);
105    ///
106    ///
107    /// ```
108    /// 
109    /// [`CallMut::mut_call_`]: ./trait.CallMut.html#tymethod.mut_call_
110    #[inline(always)]
111    fn mut_call<P>(&mut self, params: P) -> Self::Returns
112    where
113        Self: CallMut<P>
114    {
115        self.mut_call_(params)
116    }
117
118    /// For calling [`CallInto::into_call_`],
119    /// with the ability to specify the types of the arguments..
120    ///
121    /// # Example
122    ///
123    /// ```rust
124    /// use core_extensions::{impl_call, CallExt};
125    ///
126    /// use std::iter::FromIterator;
127    ///
128    /// struct IntoElem<T>(T);
129    ///
130    /// impl_call! { 
131    ///     fn into_call[T](self: IntoElem<T>, nth: usize) -> Option<T::Item>
132    ///     where[ T: IntoIterator ]
133    ///     {
134    ///         self.0.into_iter().nth(nth)
135    ///     }
136    /// }
137    /// 
138    /// let list = vec![3, 5, 8, 13, 21, 34, 55, 89];
139    /// 
140    /// // The turbofish operator can be used to specify the types of the arguments.
141    /// assert_eq!(IntoElem(list.clone()).into_call::<usize>(0), Some(3));
142    /// 
143    /// assert_eq!(IntoElem(list.clone()).into_call(1), Some(5));
144    /// 
145    /// assert_eq!(IntoElem(list.clone()).into_call(2), Some(8));
146    /// 
147    /// assert_eq!(IntoElem(list.clone()).into_call(3), Some(13));
148    /// 
149    /// assert_eq!(IntoElem(list.clone()).into_call(7), Some(89));
150    ///
151    /// ```
152    /// 
153    /// [`CallInto::into_call_`]: ./trait.CallInto.html#tymethod.into_call_
154    #[inline(always)]
155    fn into_call<P>(self, params: P) -> Self::Returns
156    where
157        Self: Sized,
158        Self: CallInto<P>
159    {
160        self.into_call_(params)
161    }
162}
163
164impl<T: ?Sized> CallExt for T {}
165
166
167/// Implementable alternative to [`std::ops::Fn`].
168///
169/// # Parameters
170///
171/// The `Call*` traits encode multiple parameters like this:
172/// 
173/// - 0 parameters: by taking a `()` parameter, eg: `foo.ref_call(())`.
174/// 
175/// - 1 parameters: by taking the single parameter, eg: `foo.ref_call(10)`.
176/// 
177/// - 2 or more parameters: by taking a tuple of the parameters, eg: `foo.ref_call((10, 20))`.
178/// 
179/// # Example
180///
181/// ```rust
182/// use core_extensions::{impl_call, CallExt};
183///
184/// struct MulBy<T>(T);
185///
186/// impl_call! { 
187///     fn ref_call[T](self: MulBy<T>, lhs: T ) -> T
188///     where[ T: Clone + std::ops::Mul<Output = T> ]
189///     {
190///         lhs * self.0.clone()
191///     }
192/// }
193/// 
194/// let two = MulBy(2);
195/// let seven = MulBy(7);
196/// 
197/// assert_eq!(two.ref_call(3), 6);
198/// assert_eq!(two.ref_call(5), 10);
199/// 
200/// assert_eq!(seven.ref_call(3), 21);
201/// assert_eq!(seven.ref_call(5), 35);
202/// 
203/// ```
204///
205/// # Closure impls
206///
207/// Closures implement the `Call*` traits,
208/// and they always require a tuple of the parameters to be passed in.
209///
210/// ```rust
211/// use core_extensions::CallExt;
212///
213/// let fn_0 = || 10;
214/// assert_eq!(fn_0.ref_call(()), 10);
215///
216/// let fn_1 = |a: i32| a + 10;
217/// assert_eq!(fn_1.ref_call((5,)), 15);
218///
219/// let fn_2 = |a: i32, b: i32| a + b;
220/// assert_eq!(fn_2.ref_call((8, 13)), 21);
221/// ```
222///
223/// [`std::ops::Fn`]: https://doc.rust-lang.org/core/ops/trait.Fn.html
224pub trait CallRef<Params>: CallMut<Params> {
225    /// calls this function
226    fn ref_call_(&self, params: Params) -> Self::Returns;
227}
228
229/// Implementable alternative to [`std::ops::FnMut`].
230///
231/// # Parameters
232///
233/// The `Call*` traits encode multiple parameters like this:
234/// 
235/// - 0 parameters: by taking a `()` parameter, eg: `foo.ref_call(())`.
236/// 
237/// - 1 parameters: by taking the single parameter, eg: `foo.ref_call(10)`.
238/// 
239/// - 2 or more parameters: by taking a tuple of the parameters, eg: `foo.ref_call((10, 20))`.
240/// 
241/// # Example
242/// 
243/// ```rust
244/// use core_extensions::{impl_call, CallExt};
245///
246/// struct Reporter{
247///     line: u32,
248/// }
249///
250/// impl_call! { 
251///     fn mut_call(self: Reporter, buffer: &mut String, person: &str, score: u32) {
252///         use std::fmt::Write;
253///
254///         writeln!(buffer, "{}- {}: {}", self.line, person, score).unwrap();
255///         
256///         self.line += 1;
257///     }
258/// }
259///
260/// let mut reporter = Reporter{line: 0};
261/// 
262/// let mut buffer = String::new();
263///
264/// reporter.mut_call((&mut buffer, "foo", 10));
265/// reporter.mut_call((&mut buffer, "bar", 7));
266/// reporter.mut_call((&mut buffer, "baz", 1000));
267///
268/// assert_eq!(
269///     buffer,
270///     "\
271///         0- foo: 10\n\
272///         1- bar: 7\n\
273///         2- baz: 1000\n\
274///     "
275/// );
276///
277/// ```
278///
279///
280/// # Closure impls
281///
282/// Closures implement the `Call*` traits,
283/// and they always require a tuple of the parameters to be passed in.
284///
285/// ```rust
286/// use core_extensions::CallExt;
287///
288/// let mut i = 0;
289///
290/// let mut fn_0 = ||{i += 1; i};
291/// assert_eq!(fn_0.mut_call(()), 1);
292///
293/// let mut fn_1 = |a: i32|{i += 1; a + i};
294/// assert_eq!(fn_1.mut_call((5,)), 7);
295///
296/// let mut fn_2 = |a: i32, b: i32|{i += 1; a + b + i};
297/// assert_eq!(fn_2.mut_call((8, 13)), 24);
298/// ```
299/// 
300/// [`std::ops::FnMut`]: https://doc.rust-lang.org/core/ops/trait.FnMut.html
301pub trait CallMut<Params>: CallInto<Params> {
302    /// calls this function
303    fn mut_call_(&mut self, params: Params) -> Self::Returns;
304}
305
306/// Implementable alternative to [`std::ops::FnOnce`].
307///
308/// # Parameters
309///
310/// The `Call*` traits encode multiple parameters like this:
311/// 
312/// - 0 parameters: by taking a `()` parameter, eg: `foo.ref_call(())`.
313/// 
314/// - 1 parameters: by taking the single parameter, eg: `foo.ref_call(10)`.
315/// 
316/// - 2 or more parameters: by taking a tuple of the parameters, eg: `foo.ref_call((10, 20))`.
317/// 
318/// # Example
319///
320/// ```rust
321/// use core_extensions::{impl_call, CallExt};
322///
323/// use std::iter::FromIterator;
324///
325/// struct Duplicator<T>(T);
326///
327/// impl_call! { 
328///     fn into_call[T](self: Duplicator<T>) -> T
329///     where[
330///         T: IntoIterator + Default,
331///         T: FromIterator<<T as IntoIterator>::Item>,
332///         T::Item: Clone,
333///     ] {
334///         self.0
335///             .into_iter()
336///             .flat_map(|elem| vec![elem; 2] )
337///             .collect()
338///     }
339/// }
340/// 
341/// assert_eq!(Duplicator(vec![3, 5]).into_call(()), vec![3, 3, 5, 5]);
342///
343/// assert_eq!(Duplicator(vec!["hi", "ho"]).into_call(()), vec!["hi", "hi", "ho", "ho"]);
344/// 
345/// ```
346///
347/// # Closure impls
348///
349/// Closures implement the `Call*` traits,
350/// and they always require a tuple of the parameters to be passed in.
351///
352/// ```rust
353/// use core_extensions::CallExt;
354///
355/// let orig = vec![3, 5, 8, 13, 21, 34];
356///
357/// let list = orig.clone();
358/// let fn_0 = || list.into_iter().next();
359/// assert_eq!(fn_0.into_call(()), Some(3));
360///
361/// let list = orig.clone();
362/// let fn_1 = |i: usize| list.into_iter().nth(i);
363/// assert_eq!(fn_1.into_call((3,)), Some(13));
364///
365/// let list = orig.clone();
366/// let fn_2 = |s: usize, i: usize| list.into_iter().skip(s).nth(i);
367/// assert_eq!(fn_2.into_call((3, 1)), Some(21));
368/// ```
369///
370/// [`std::ops::FnOnce`]: https://doc.rust-lang.org/core/ops/trait.FnOnce.html
371pub trait CallInto<Params> {
372    /// The return type of this function
373    type Returns;
374    /// calls this function
375    fn into_call_(self, params: Params) -> Self::Returns;
376}
377
378macro_rules! impl_call {
379    ( $( [$($ty:ident),+] )* ) => {
380        $(
381            impl<$($ty,)* Func,Ret> CallRef<($($ty,)*)> for Func
382            where Func:Fn($($ty,)*)->Ret
383            {
384                #[allow(non_snake_case)]
385                fn ref_call_(&self,($($ty,)*):($($ty,)*))->Ret{
386                    self($($ty),*)
387                }
388            }
389
390            impl<$($ty,)* Func,Ret> CallMut<($($ty,)*)> for Func
391            where Func:FnMut($($ty,)*)->Ret
392            {
393                #[allow(non_snake_case)]
394                fn mut_call_(&mut self,($($ty,)*):($($ty,)*))->Ret{
395                    self($($ty,)*)
396                }
397            }
398
399            impl<$($ty,)* Func,Ret> CallInto<($($ty,)*)> for Func
400            where Func:FnOnce($($ty,)*)->Ret
401            {
402                type Returns = Ret;
403
404                #[allow(non_snake_case)]
405                fn into_call_(self,($($ty,)*):($($ty,)*))->Ret{
406                    self($($ty,)*)
407                }
408            }
409
410        )*
411    }
412}
413
414impl<F, Ret> CallRef<()> for F
415where
416    F: Fn() -> Ret,
417{
418    fn ref_call_(&self, _: ()) -> Ret {
419        self()
420    }
421}
422
423impl<F, Ret> CallMut<()> for F
424where
425    F: FnMut() -> Ret,
426{
427    fn mut_call_(&mut self, _: ()) -> Ret {
428        self()
429    }
430}
431
432impl<F, Ret> CallInto<()> for F
433where
434    F: FnOnce() -> Ret,
435{
436    type Returns = Ret;
437    fn into_call_(self, _: ()) -> Ret {
438        self()
439    }
440}
441
442impl_call! {
443    [A]
444    [A,B]
445    [A,B,C]
446    [A,B,C,D]
447    [A,B,C,D,E]
448    [A,B,C,D,E,F]
449    [A,B,C,D,E,F,G]
450    [A,B,C,D,E,F,G,H]
451    [A,B,C,D,E,F,G,H,I]
452    [A,B,C,D,E,F,G,H,I,J]
453    [A,B,C,D,E,F,G,H,I,J,K]
454    [A,B,C,D,E,F,G,H,I,J,K,L]
455}
456
457/**
458This macro allows more ergonomically implementing the 
459[`CallRef`](./callable/trait.CallRef.html) /
460[`CallMut`](./callable/trait.CallMut.html) /
461[`CallInto`](./callable/trait.CallInto.html)
462traits .
463
464# Examples
465
466### Implementing `CallRef`.
467
468```rust
469
470use core_extensions::{impl_call, CallExt};
471
472struct Environment;
473
474impl_call!{
475    fn ref_call(self: Environment, printing: &str ) {
476        println!("printing '{}'",printing);
477    }
478}
479
480Environment.ref_call("what the ...");
481
482```
483
484### Implementing `CallMut`.
485
486Also demonstrates a polymorphic function, not possible in Rust closures yet.
487
488*/
489#[cfg_attr(feature = "phantom", doc = " ```rust")]
490#[cfg_attr(not(feature = "phantom"), doc = " ```ignore")]
491/**
492use core_extensions::{impl_call, AsPhantomData, CallExt};
493
494use std::marker::PhantomData;
495
496struct Environment{
497    i: u16,
498}
499
500impl_call!{
501    // The PhantomData parameter is necessary because closures can't return a generic type
502    // that doesn't appear in the parameter.
503    fn mut_call[T](self: Environment, _a: PhantomData<T>) -> T
504    where [ u16: Into<T>, ]
505    {
506        self.i += 1;
507        self.i.into()
508    }
509}
510
511let mut env = Environment{i:0};
512assert_eq!(env.mut_call(u16::PHANTOM), 1);
513assert_eq!(env.mut_call(u32::PHANTOM), 2);
514```
515
516
517### Implementing `CallInto`.
518
519```rust
520use core_extensions::{impl_call, CallExt};
521
522struct Environment<T>(T);
523
524impl_call!{
525    fn into_call[T](self: Environment<T>)->T{
526        self.0
527    }
528}
529
530
531let env = Environment("hello");
532assert_eq!(env.into_call(()), "hello");
533```
534
535
536
537
538# Syntax
539
540
541`$( ... )*` means repeated 0 or more times.
542
543`$( ... )+` means repeated 1 or more times.
544
545`$( ... )?` means that this is optional.
546
547 `< ... >` is a variable,replaced with whatever it refers to.
548
549
550```text
551
552$(#[$meta:meta])*
553
554// <fn_method_name> is one of (into_call|mut_call|ref_call),determining which trait
555// is implemented.
556fn <fn_method_name>
557
558// Optionally declares the generic parameters of the function.
559$( [ $( <generic_parameter> )* ] )?
560
561// <self_type> is the type of the closure environment,which is implementing the Call traits.
562// <function_parameter> are optional function parameters.
563(   
564    self: <self_type>
565    $(, <function_parameter> )*
566    $(,)?
567)
568
569//<return_tyoe> optional return type,defaults to '()'.
570$( -> <return_type> )?
571
572// An optional where clause,
573// all tokens inside `[...]` get copied directly to the where clause of the impl.
574$( where [ $( <where_predicates> )* ] )*
575
576{
577    // The definition of the function
578    <function_definition>
579}
580
581
582
583```
584
585
586
587[`CallRef`]: ./callable/trait.CallRef.html
588
589[`CallMut`]: ./callable/trait.CallMut.html
590
591[`CallInto`]: ./callable/trait.CallInto.html
592
593*/
594#[cfg(feature = "callable")]
595#[cfg_attr(feature = "docsrs", doc(cfg(feature = "callable")))]
596#[macro_export]
597macro_rules! impl_call{
598    (
599        $(#[$meta:meta])*
600        fn $fn_kind:ident
601        $( [ $( $fn_gen_params:tt )* ] )*
602        ( $( $fn_params:tt )* )
603        $( -> $ret_ty:ty )?
604        $( where [ $( $where_preds:tt )* ] )*
605        $body:block
606
607    )=>{
608        $crate::__priv_impl_call!{
609            outer_step_a;
610            (
611                $(#[$meta])*
612                fn $fn_kind
613                [ $( $( $fn_gen_params )* )* ]
614            )
615            ( $( $fn_params )* )
616            ($($ret_ty)?)
617            (
618                where [ $( $( $where_preds )* )* ]
619                $body
620            )
621        }
622    };
623}
624
625#[doc(hidden)]
626#[macro_export]
627macro_rules! __priv_impl_call {
628    (outer_step_a; $prefn:tt $fn_params:tt () $postfn:tt ) => {
629        $crate::__priv_impl_call!{outer_step_b; $prefn $fn_params (()) $postfn}
630    };
631    (outer_step_a; $prefn:tt $fn_params:tt ($ret_ty:ty) $postfn:tt ) => {
632        $crate::__priv_impl_call!{outer_step_b; $prefn $fn_params ($ret_ty) $postfn}
633    };
634    
635   (outer_step_b;
636        ($($prefn:tt)*)
637        ( $self:ident: $fn_ty:ty, $params:ident : $params_ty:ty $(,)? )
638        ($ret_ty:ty)
639        ($($postfn:tt)*)
640    ) => {
641        $crate::__priv_impl_call!{
642            inner_fn;
643            $($prefn)*
644            ( $self: $fn_ty, $params, $params_ty)
645            -> $ret_ty
646            $($postfn)*
647        }
648    };
649   (outer_step_b;
650        ($($prefn:tt)*)
651        ( $self:ident: $fn_ty:ty  $(, $params:ident : $params_ty:ty )* $(,)? )
652        ($ret_ty:ty)
653        ($($postfn:tt)*)
654    ) => {
655        $crate::__priv_impl_call!{
656            inner_fn;
657            $($prefn)*
658            ( $self: $fn_ty, ($($params),*), ($($params_ty),*))
659            -> $ret_ty
660            $($postfn)*
661        }
662    };
663
664    (inner_fn;
665        $(#[$meta:meta])*
666        fn into_call
667        [ $( $fn_gen_params:tt )* ]
668        ( $self:ident: $fn_ty:ty, $params_pati:pat, $params_ty:ty)
669        -> $ret_ty:ty
670        where [ $( $where_preds:tt )* ]
671        $body:block
672    )=>{
673        $(#[$meta])*
674        impl< $($fn_gen_params)* > $crate::CallInto<$params_ty> for $fn_ty
675        where
676            $( $where_preds )*
677        {
678            type Returns = $ret_ty;
679
680            fn into_call_($self, $params_pati: $params_ty) -> $ret_ty 
681            $body
682        }
683    };
684    (inner_fn;
685        $(#[$meta:meta])*
686        fn mut_call
687        [ $( $fn_gen_params:tt )* ]
688        ( $self:ident: $fn_ty:ty, $params_pati:pat, $params_ty:ty)
689        -> $ret_ty:ty
690        where [ $( $where_preds:tt )* ]
691        $body:block
692    )=>{
693        $(#[$meta])*
694        impl< $($fn_gen_params)* > $crate::CallInto<$params_ty> for $fn_ty
695        where $( $where_preds )*
696        {
697            type Returns = $ret_ty;
698
699            #[inline(always)]
700            fn into_call_(mut $self, param : $params_ty) -> $ret_ty {
701                $crate::CallMut::mut_call_(&mut $self, param)
702            }
703        }
704
705        $(#[$meta])*
706        impl< $($fn_gen_params)* > $crate::CallMut<$params_ty> for $fn_ty
707        where $( $where_preds )*
708        {
709            fn mut_call_(&mut $self, $params_pati: $params_ty) -> $ret_ty
710            $body
711        }
712    };
713
714    (inner_fn;
715        $(#[$meta:meta])*
716        fn ref_call
717        [ $( $fn_gen_params:tt )* ]
718        ( $self:ident: $fn_ty:ty, $params_pati:pat, $params_ty:ty)
719        -> $ret_ty:ty
720        where [ $( $where_preds:tt )* ]
721        $body:block
722    )=>{
723        $(#[$meta])*
724        impl< $($fn_gen_params)* > $crate::CallInto<$params_ty> for $fn_ty
725        where $( $where_preds )*
726        {
727            type Returns = $ret_ty;
728
729            #[inline(always)]
730            fn into_call_($self, param : $params_ty) -> $ret_ty {
731                $crate::CallRef::ref_call_(&$self, param)
732            }
733        }
734
735        $(#[$meta])*
736        impl< $($fn_gen_params)* > $crate::CallMut<$params_ty> for $fn_ty
737        where $( $where_preds )*
738        {
739            #[inline(always)]
740            fn mut_call_(&mut $self, param : $params_ty) -> $ret_ty {
741                $crate::CallRef::ref_call_($self, param)
742            }
743        }
744
745        $(#[$meta])*
746        impl< $($fn_gen_params)* > $crate::CallRef<$params_ty> for $fn_ty
747        where $( $where_preds )*
748        {
749            fn ref_call_(&$self, $params_pati: $params_ty) -> $ret_ty
750            $body
751        }
752    };
753}