rust_tailcall/
lib.rs

1/// Represents a tail call that can be either a continuation or a completed result.
2pub enum TailCall<T> {
3    /// A continuation that holds a deferred computation.
4    Continue(Box<dyn Fn() -> TailCall<T>>),
5    /// A completed computation with a result.
6    Done(T),
7}
8
9impl<T> TailCall<T> {
10    /// Applies the current step and returns the next `TailCall`.
11    ///
12    /// # Panics
13    /// Panics if called on a completed computation.
14    pub fn apply(&self) -> TailCall<T> {
15        match self {
16            TailCall::Continue(f) => f(),
17            TailCall::Done(_) => panic!("Cannot apply on completed TailCall"),
18        }
19    }
20
21    /// Checks whether the computation is completed.
22    pub fn is_completed(&self) -> bool {
23        matches!(self, TailCall::Done(_))
24    }
25
26    /// Returns the result if the computation is completed.
27    pub fn result(&self) -> Option<&T> {
28        match self {
29            TailCall::Done(val) => Some(val),
30            _ => None,
31        }
32    }
33
34    /// Executes the computation by iterating until a completed result is found.
35    pub fn invoke(self) -> T {
36        let mut current = self;
37        loop {
38            match current {
39                TailCall::Continue(f) => {
40                    current = f();
41                }
42                TailCall::Done(val) => {
43                    return val;
44                }
45            }
46        }
47    }
48}
49
50
51/// Represents a tail call that can be either a continuation or a completed result.
52/// Uses static dispatch by parameterizing over the function type `F`.
53pub enum MutableTailCall<T, F>
54where
55    F: Fn() -> MutableTailCall<T, F>,
56{
57    /// A continuation that holds a deferred computation.
58    Continue(F),
59    /// A completed computation with a result.
60    Done(T),
61}
62
63impl<T, F> MutableTailCall<T, F>
64where
65    F: Fn() -> MutableTailCall<T, F>,
66{
67    /// Applies the current step and returns the next `TailCall`.
68    ///
69    /// # Panics
70    /// Panics if called on a completed computation.
71    pub fn apply(self) -> MutableTailCall<T, F> {
72        match self {
73            MutableTailCall::Continue(f) => f(),
74            MutableTailCall::Done(_) => panic!("Cannot apply on completed TailCall"),
75        }
76    }
77
78    /// Checks whether the computation is completed.
79    pub fn is_completed(&self) -> bool {
80        matches!(self, MutableTailCall::Done(_))
81    }
82
83    /// Returns the result if the computation is completed.
84    pub fn result(&self) -> Option<&T> {
85        match self {
86            MutableTailCall::Done(val) => Some(val),
87            _ => None,
88        }
89    }
90
91    /// Executes the computation by iterating until a completed result is found.
92    pub fn invoke(mut self) -> T {
93        loop {
94            match self {
95                MutableTailCall::Continue(f) => {
96                    self = f();
97                }
98                MutableTailCall::Done(val) => {
99                    return val;
100                }
101            }
102        }
103    }
104}