Created
September 7, 2016 21:02
-
-
Save iopq/471ed71a1a51297673b167dca15616c6 to your computer and use it in GitHub Desktop.
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 characters
//! 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