Created
September 7, 2016 21:02
-
-
Save iopq/471ed71a1a51297673b167dca15616c6 to your computer and use it in GitHub Desktop.
Revisions
-
iopq created this gist
Sep 7, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,83 @@ //! 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<T> where &'a str: Into<T> { 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<T>, b: &'a str, include: bool) -> Option<T> where &'a str: Into<T> { a.op( if_some(b, include) ) } //only perform an expensive operation if the condition is true fn if_some<T: Into<U>, U>(a: T, cond: bool) -> Option<U> { if cond { Some(a.into()) } else { None } } #[cfg(test)] mod tests { use super::append; #[test] fn none() { assert_eq!(None::<String>, 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)); } }