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}