thunk_simple/lib.rs
1//! Simpler alternative to the `thunk` crate, containing only one `Thunk` type, and conversion between Iterators and Thunks
2
3/// The `Thunk<T>` type.
4/// This type is not evaluated until the `unwrap` method is called.
5/// The inner value cannot be referenced until it's unwrapped.
6pub struct Thunk<'f,T>(Box<dyn (FnOnce()-> T) + 'f>) where T: 'f;
7
8impl<'f,T> Thunk<'f,T> where T:'f {
9
10 /// Create a new `Thunk<T>` from a closure or function returning `T`
11 pub fn new<NT,NF>(body: NF) -> Thunk<'f,NT> where
12 NF: (FnOnce() -> NT) + 'f
13 {
14 Thunk(Box::new(body))
15 }
16
17 /// Create a new `Thunk<T>` from an already-calculated value T
18 pub fn new_const<NT: 'f>(nt: NT) -> Thunk<'f,NT> {
19 Self::new(|| nt)
20 }
21
22 /// Map a `Thunk<T>` into a `Thunk<U>`.
23 /// This method supplies the previous thunk value unevaluated as an argument.
24 pub fn map_lazy<NT,NF>(self,body: NF) -> Thunk<'f,NT> where
25 NF: (FnOnce(Thunk<'f,T>) -> NT) + 'f
26 {
27 Thunk::<'f,NT>::new(|| (body)(self))
28 }
29
30 /// Map a `Thunk<T>` into a `Thunk<U>`.
31 /// This method provides an already-evaluated T to the mapping function
32 pub fn map<NT,NF>(self,body: NF) -> Thunk<'f,NT> where
33 NF: (FnOnce(T) -> NT) + 'f
34 {
35 Thunk::<'f,NT>::new(|| (body)((self.0)()))
36 }
37
38 /// Unwrap, and therefore calculate, the value `T` contained inside this thunk
39 ///
40 /// ## Panics
41 /// If the Thunk was created `from` an Iterator, the Thunk may panic if the Iterator yields less than one element.
42 /// Otherwise only panics when any function involved in calculating the value panics.
43 pub fn unwrap(self) -> T {
44 (self.0)()
45 }
46
47}
48
49impl<'f,T,I> From<I> for Thunk<'f,T> where
50 T: 'f,
51 I: Iterator<Item = T> + 'f
52{
53 fn from(mut iter: I) -> Self {
54 Self::new(move || iter.next().unwrap())
55 }
56}
57
58impl<'f,T> IntoIterator for Thunk<'f,T> where
59 T: 'f
60{
61 type IntoIter = IntoIter<'f,T>;
62 type Item = T;
63
64 fn into_iter(self) -> Self::IntoIter {
65 IntoIter(Some(self))
66 }
67}
68
69/// Simple IntoIter Iterator, that yields the value of the Thunk then None
70pub struct IntoIter<'f,T>(Option<Thunk<'f,T>>);
71
72impl<'f,T> Iterator for IntoIter<'f,T> {
73 type Item = T;
74 fn next(&mut self) -> Option<Self::Item> {
75 if let Some(thunk) = std::mem::take(&mut self.0) {
76 Some(thunk.unwrap())
77 } else {
78 None
79 }
80 }
81}