//! The `fizzbuzz` crate provides the way to get a customizable fizzbuzz implementation //! //! # Examples //! //! ``` //! let mut acc = "".to_string(); //! for i in 1..16 { //! acc = acc + &*fizzbuzz::cowbuzz(&[ //! ("Fizz", &|i: i32| i % 3 == 0), //! ("Buzz", &|i: i32| i % 5 == 0), //! ], i) + " "; //! } //! //! assert_eq!(acc, "1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz ".to_string()); //! ``` extern crate monoid; use monoid::Monoid; use std::borrow::Cow; use std::convert::Into; ///takes a tuple of strings and conditions ///shows the numbers if conditions are false pub fn fizzbuzz<'a>(tuples: &[(&'a str, &Fn(i32) -> bool)], i: i32) -> String { let default = || i.to_string(); accumulate(tuples, i).unwrap_or_else(default) //unwrap_or_else is equivalent to fromMaybe } ///takes a tuple of strings and conditions ///shows the numbers if conditions are false ///faster than using a String pub fn cowbuzz<'a>(tuples: &[(&'a str, &Fn(i32) -> bool)], i: i32) -> Cow<'a, str> { let default = || i.to_string().into(); accumulate(tuples, i).unwrap_or_else(default) //unwrap_or_else is equivalent to fromMaybe } //does the monoid operation on the slice of tuples if the closure evaluates to true fn accumulate<'a, T: Monoid>(tuples: &[(&'a str, &Fn(i32) -> bool)], i: i32) -> Option where &'a str: Into { tuples.iter() .filter(|&(_,include_fn)| include_fn(i)) .map(|(concat_str,_)| concat_str) .fold(None, |acc, concat_str| acc.op(concat_str)); } //concatenates the strings if the condition is met fn append<'a, T: Monoid>(a: Option, b: &'a str, include: bool) -> Option where &'a str: Into { a.op( if_some(b, include) ) } //only perform an expensive operation if the condition is true fn if_some, U>(a: T, cond: bool) -> Option { if cond { Some(a.into()) } else { None } } #[cfg(test)] mod tests { use super::append; #[test] fn none() { assert_eq!(None::, append(None, "b", false)); } #[test] fn a() { assert_eq!(Some("a".to_string()), append(Some("a".to_string()), "b", false)); } #[test] fn b() { assert_eq!(Some("b".to_string()), append(None, "b", true)); } #[test] fn ab() { assert_eq!(Some("ab".to_string()), append(Some("a".to_string()), "b", true)); } }