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
//! This crate implements an easy way to cache values for
//! a function. If you have a slow running function, this
//! can be used to speed up successive runs dramatically.
//! It is also quite useful for memoization of recursive
//! functions, to prevent calculating the same function
//! twice in different calls.
//!
//! Of particular note, this caching is done without
//! cloning or copying, allowing functions to return
//! large objects, while the cache only returns a reference
//! to them instead of copying them.
//!
//! # Allowed functions
//! This crate attempts to remain fairly flexible with
//! the functions it accepts. All of the following should
//! be allowed:
//! * [`fn`][fn primitive] types.
//! * [`Fn`] types that have no references.
//! * [`Fn`] + 'static types that take only static references.
//! * [`Fn`] + 'a types that take references of lifetime 'a.
//!
//! For obvious reasons, [`FnMut`] and [`FnOnce`] are not allowed,
//! as functions need to be rerunnable and pure.
//!
//! # Examples
//!
//! The caches can handle recursive functions, with a shortcut
//! for defining it with non-recursive functions. Each cache
//! has a `recursive` function to create a recursion capable
//! cache, but requires the function to accept the cache as the
//! first argument. Each `new` function takes a function that
//! does not require the cache as an argument.
//!
//! ## Non-recursive
//!
//! Here is an example for a function that takes a while to
//! calculate. Instead of running the calculations each time
//! you'd like to do it just once, and recall the value. The
//! results are stored in a [`HashCache`] for random access.
//!
//! ```rust
//! use fn_cache::{FnCache, HashCache};
//! use std::{thread, time};
//!
//! let sleep_time = time::Duration::from_secs(3);
//!
//! let mut cache = HashCache::new(|&x| {
//! thread::sleep(sleep_time);
//! x
//! });
//!
//! let start = time::Instant::now();
//! assert_eq!(cache.get(100), &100);
//! assert_eq!(cache.get(100), &100);
//!
//! // time elapsed is only slightly longer than the sleep time
//! // far less than twice.
//! assert!(time::Instant::now() - start < sleep_time.mul_f32(1.1));
//! ```
//!
//! ## Recursive
//!
//! The following example shows a recursive fibonacci
//! implementation, which would be O(2ⁿ) without
//! memoization (caching). With memoization, it becomes
//! O(n), and can easily be calculated.
//!
//! ```rust
//! use fn_cache::{FnCache, HashCache};
//!
//! let mut cache = HashCache::<u8,u128>::recursive(|cache, x|
//! match x {
//! 0 => 0,
//! 1 => 1,
//! _ => *cache.get(x - 1) + *cache.get(x - 2),
//! }
//! );
//!
//! assert_eq!(
//! *cache.get(186),
//! 332_825_110_087_067_562_321_196_029_789_634_457_848
//! );
//! ```
//!
//! For even bigger results, the [num] crate might be employed.
//! In order to avoid copying the `BigUint`s while accessing the
//! cache twice, using [`FnCacheMany::get_many`] can be used to get
//! multiple values at once, to avoid trying to take a reference and
//! then mutating again. Additionally, since the inputs start at 0
//! and each value must be filled before the next is calculated, you
//! might use a [`VecCache`] as an optimization.
//!
//! ```rust
//! use fn_cache::{FnCache, FnCacheMany, VecCache};
//! use num_bigint::BigUint;
//!
//! let mut cache = VecCache::recursive(|cache, x|
//! match x {
//! 0 => BigUint::new(vec![0]),
//! 1 => BigUint::new(vec![1]),
//! _ => cache.get_many([x - 1, x - 2]).into_iter().sum(),
//! }
//! );
//!
//! assert_eq!(
//! cache.get(999),
//! &BigUint::parse_bytes(b"26863810024485359386146727202142923967616609318986952340123175997617981700247881689338369654483356564191827856161443356312976673642210350324634850410377680367334151172899169723197082763985615764450078474174626", 10).unwrap()
//! );
//! ```
//!
//! ## Implementing your own Container
//!
//! Maybe you've got a more efficient container for your use case or access pattern. You can have
//! [`GenericCache`] do most of the heavy lifting (in fact that's what `HashCache` and `BTreeCache`
//! do!), by simply implementing [`SparseContainer`] on your storage type.
//!
//! ```rust
//! use std::collections::BTreeMap;
//! use fn_cache::{GenericCache, container::SparseContainer};
//!
//! type MyCache<'f, I, O> = GenericCache<'f, MyContainer<I, O>>;
//!
//! struct MyContainer<I, O>(BTreeMap<I, O>);
//!
//! impl<I: Ord, O> SparseContainer for MyContainer<I, O> {
//! type Input = I;
//! type Output = O;
//!
//! fn get(&self, input: &Self::Input) -> Option<&Self::Output> {
//! self.0.get(input)
//! }
//!
//! fn put(&mut self, input: Self::Input, output: Self::Output) -> &Self::Output {
//! self.0.entry(input).or_insert(output)
//! }
//! }
//! ```
//!
//! [fn primitive]: https://doc.rust-lang.org/std/primitive.fn.html
//! [`Rc`]: std::rc::Rc
//! [num]: https://docs.rs/num/
pub use crateBTreeCache;
pub use crate;
pub use crateGenericCache;
pub use crateHashCache;
pub use crateVecCache;