Skip to content

Instantly share code, notes, and snippets.

@iopq
Created September 7, 2016 21:02
Show Gist options
  • Save iopq/471ed71a1a51297673b167dca15616c6 to your computer and use it in GitHub Desktop.
Save iopq/471ed71a1a51297673b167dca15616c6 to your computer and use it in GitHub Desktop.
//! 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));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment