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}