X-Git-Url: https://piware.de/gitweb/?p=learn-rust.git;a=blobdiff_plain;f=concepts%2Fsrc%2Flib.rs;fp=concepts%2Fsrc%2Flib.rs;h=b7e5eb8f1df11116f8d94fd31fb1afe29491d087;hp=0000000000000000000000000000000000000000;hb=b653e9fe9d8492f2d4b5419721f7e00b392055f9;hpb=8c240f514e17c9a935f5f392e6a87779ae1c09e8 diff --git a/concepts/src/lib.rs b/concepts/src/lib.rs new file mode 100644 index 0000000..b7e5eb8 --- /dev/null +++ b/concepts/src/lib.rs @@ -0,0 +1,110 @@ +use std::fs::File; +use std::io::prelude::*; +use std::collections::HashMap; + +pub fn read_file(path: &str) -> Result { + let mut s = String::new(); + File::open(path)? + .read_to_string(&mut s)?; + Ok(s) +} + +// needs Copy trait, good for simple types +pub fn largest(list: &[T]) -> T { + let mut result = list[0]; + for &i in list { + if i > result { + result = i; + } + } + result +} + +// expensive for large strings, don't use that +pub fn largest_clone(list: &[T]) -> T { + let mut result = list[0].clone(); + for i in list { + if *i > result { + result = i.clone(); + } + } + result +} + +// good for everything, but more expensive for simple types +pub fn largest_ref(list: &[T]) -> &T { + let mut result = &list[0]; + for i in list { + if i > result { + result = i; + } + } + result +} + +pub fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { + if x.len() > y.len() { + x + } else { + y + } +} + +/// Wrap and cache an expensive calculation +/// +/// This calls a closure just once for every distinct argument. Any subsequent +/// call to `.value()` with the same argument uses the cached value. +pub struct Cacher +where + T: Fn(A) -> V, + A: Eq + Copy + std::hash::Hash, + V: Copy, +{ + calc: T, + values: HashMap, +} + +impl Cacher +where + T: Fn(A) -> V, + A: Eq + Copy + std::hash::Hash, + V: Copy, +{ + pub fn new(calc: T) -> Cacher { + Cacher { calc, values: HashMap::new() } + } + + pub fn value(&mut self, arg: A) -> V { + match self.values.get(&arg) { + Some(v) => *v, + None => { + let v = (self.calc)(arg); + self.values.insert(arg, v); + v + } + } + } +} + +pub struct Counter5 { + count: u32 +} + +impl Counter5 { + pub fn new() -> Counter5 { + Counter5 { count: 0 } + } +} + +impl Iterator for Counter5 { + type Item = u32; + + fn next(&mut self) -> Option { + if self.count < 5 { + self.count += 1; + Some(self.count) + } else { + None + } + } +}