Skip to content

Instantly share code, notes, and snippets.

@iopq
Created September 7, 2016 21:02
Show Gist options
  • Select an option

  • Save iopq/471ed71a1a51297673b167dca15616c6 to your computer and use it in GitHub Desktop.

Select an option

Save iopq/471ed71a1a51297673b167dca15616c6 to your computer and use it in GitHub Desktop.

Revisions

  1. iopq created this gist Sep 7, 2016.
    83 changes: 83 additions & 0 deletions lib.rs
    Original 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));
    }
    }