1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
//! Provides interfaces and implementations for logic constructs that return values without accepting arguments, either via closure captures, global state, calculation or otherwise. #[cfg(test)] mod tests; use std::rc::Rc; /// An interface for immediate evaluation (without caching) for any types and cached (lazy) evaluation for types that implement `Clone`, including those that implement [`Copy`], integers and floats being the simplest examples. pub trait Evaluator { /// The type that the evaluator evaluates to. type Output; /// Evaluates and returns the result. Because evaluators may possibly involve caching, a mutable borrow of `self` is required. Thus all evaluators must be mutable. /// # Panics /// Panicking of this function is not defined or restricted. Refer to the documentation of implementing structs for more information. fn eval(&mut self) -> Self::Output; } /// An interface for cached (lazy) evaluation for types that do not implement `Clone` (note that `Clone` is a supertrait of `Copy`). pub trait RcEvaluator { /// The type that the evaluator evaluates to. type Output; /// Evaluates and returns a reference counter to the result. Because evaluators may possibly involve caching, a mutable borrow of `self` is required. Thus all evaluators must be mutable. /// # Panics /// Panicking of this function is not defined or restricted. Refer to the documentation of implementing structs for more information. fn eval(&mut self) -> Rc<Self::Output>; } /// Implements immediate evaluation via closures. pub struct ImmEval<Out, Cl> where Cl: FnMut() -> Out { closure: Cl } impl<Out, Cl> From<Cl> for ImmEval<Out, Cl> where Cl: FnMut() -> Out { /// Constructs the evaluator from the specified closure. fn from(cl: Cl) -> Self { ImmEval {closure: cl} } } impl<Out, Cl> Evaluator for ImmEval<Out, Cl> where Cl: FnMut() -> Out { type Output = Out; /// Evaluates and returns the result. Because evaluators may possibly involve caching, a mutable borrow of `self` is required by the [`Evaluator`](trait.Evaluator.html) trait, though immediate evaluators do not involve any. /// # Panics /// Panicking of this function is not defined or restricted and depends on the closure. fn eval(&mut self) -> Self::Output { (self.closure)() } } /// Implements cached (lazy) evaluation **of clonable types** via closures. pub struct Eval<Out, Cl> where Out: Clone, Cl: FnMut() -> Out { closure: Cl, last: Option<Out> } impl<Out, Cl> Eval<Out, Cl> where Out: Clone, Cl: FnMut() -> Out { /// Invalidates the cached value, if there is one. If the evaluator was never used after creation or was recently `flush()`ed, does nothing. pub fn flush(&mut self) { self.last = None; } } impl<Out, Cl> From<Cl> for Eval<Out, Cl> where Out: Clone, Cl: FnMut() -> Out { /// Constructs the evaluator from the specified closure. fn from(cl: Cl) -> Self { Eval {closure: cl, last: None} } } impl<Out, Cl> Evaluator for Eval<Out, Cl> where Out: Clone, Cl: FnMut() -> Out { type Output = Out; /// Evaluates and returns the result. **This includes the overhead of cloning the value, because the internal cache must be preserved. If you need to move the result every time it is evaluated, use [`ImmEval`].** /// /// Because caching evaluators, as their name suggests, store the cached value inside themselves, a mutable borrow of `self` is required. /// # Panics /// Panicking of this function is not defined or restricted and depends on the closure. fn eval(&mut self) -> Self::Output { if self.last.is_none() { self.last = Option::from((self.closure)()); } self.last.clone().unwrap() } } /// Implements cached (lazy) evaluation of clonable **and** non-clonable types via closures. pub struct RcEval<Out, Cl> where Cl: FnMut() -> Out { closure: Cl, last: Option<Rc<Out>> } impl<Out, Cl> RcEval<Out, Cl> where Cl: FnMut() -> Out { /// Disowns the cached value (destroying it if there are no other owners), if there is one. If the evaluator was never used after creation or was recently `flush()`ed, does nothing. pub fn flush(&mut self) { self.last = None; } } impl<Out, Cl> From<Cl> for RcEval<Out, Cl> where Cl: FnMut() -> Out { /// Constructs the evaluator from the specified closure. fn from(cl: Cl) -> Self { RcEval {closure: cl, last: None} } } impl<Out, Cl> RcEvaluator for RcEval<Out, Cl> where Cl: FnMut() -> Out { type Output = Out; /// Evaluates and returns an [`std::rc::Rc`] to the result. /// /// Because caching evaluators, as their name suggests, store the cached value inside themselves, a mutable borrow of `self` is required. /// # Panics /// Panicking of this function is not defined or restricted and depends on the closure. fn eval(&mut self) -> Rc<Self::Output> { if self.last.is_none() { self.last = Option::from(Rc::from((self.closure)())); } self.last.clone().unwrap() } } impl<Out, Cl> Evaluator for RcEval<Out, Cl> where Out: Clone, Cl: FnMut() -> Out { type Output = Out; /// Evaluates and returns the result. **This includes the overhead of cloning the value, because the internal cache must be preserved. If you need to move the result every time it is evaluated, use [`ImmEval`].** /// /// Because caching evaluators, as their name suggests, store the cached value inside themselves, a mutable borrow of `self` is required. /// # Panics /// Panicking of this function is not defined or restricted and depends on the closure. fn eval(&mut self) -> Self::Output { if self.last.is_none() { self.last = Option::from(Rc::from((self.closure)())); } Out::clone(&self.last.clone().unwrap()) } } /// Implements dummy evaluation of clonable **and** non-clonable types: every time the `eval()` method is called, a fixed value is returned. pub struct DummyEval<Out> { value: Out } impl<Out> From<Out> for DummyEval<Out> { /// Constructs the evaluator from the specified dummy value. fn from(value: Out) -> Self { DummyEval {value} } } impl<Out> Evaluator for DummyEval<Out> where Out: Clone { type Output = Out; /// Evaluates and returns the result. **This includes the overhead of cloning the value, because the fixed value must be preserved.** /// /// Because caching evaluators, as their name suggests, store the cached value inside themselves, a mutable borrow of `self` is required. /// # Panics /// May panic only if cloning of the inner value panics. fn eval(&mut self) -> Self::Output { self.value.clone() } }/* impl<Out> RcEvaluator for DummyEval<Out> { type Output = Out; /// Evaluates and returns an [`std::rc::Rc`] to the result. Because evaluators may possibly involve caching, a mutable borrow of `self` is required by the [`Evaluator`](trait.Evaluator.html) trait, though dummy evaluators obviously do not involve any, as no values are produced during evaluation. /// # Panics /// Guaranteed to never panic. fn eval(&mut self) -> Rc<Self::Output> { uuh dunno? } }*/