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 } } } }