From b71e253b697bae079a0cf2526209334f4b81f9a5 Mon Sep 17 00:00:00 2001 From: Adam Carpenter <53hornet@gmail.com> Date: Fri, 1 Mar 2019 14:01:17 -0500 Subject: Added functional and implemented iterators in minigrep. --- functional/src/main.rs | 210 ++++++++++++++++++++++++++++++++++++++++--------- minigrep/Cargo.toml | 1 + minigrep/src/lib.rs | 54 +++++-------- minigrep/src/main.rs | 3 +- 4 files changed, 194 insertions(+), 74 deletions(-) diff --git a/functional/src/main.rs b/functional/src/main.rs index 4fbc447..7749e58 100644 --- a/functional/src/main.rs +++ b/functional/src/main.rs @@ -1,50 +1,188 @@ -use std::thread; -use std::time::Duration; +//use std::thread; +//use std::time::Duration; +// +//struct Cacher +// where T: Fn(u32) -> u32 +//{ +// calculation: T, +// value: Option, +//} +// +//impl Cacher +// where T: Fn(u32) -> u32 +//{ +// fn new (calculation: T) -> Cacher { +// Cacher { +// calculation, +// value: None, +// } +// } +// +// fn value(&mut self, arg: u32) -> u32 { +// match self.value { +// Some(v) => v, +// None => { +// let v = (self.calculation)(arg); +// self.value = Some(v); +// v +// }, +// } +// } +//} +// +//fn main() { +// let simulated_user_specified_value = 26; +// let simulated_random_number = 3; +// +// generate_workout( +// simulated_user_specified_value, +// simulated_random_number +// ); +//} +// +//fn generate_workout(intensity: u32, random_number: u32) { +// let mut expensive_result = Cacher::new(|num| { +// println!("calculating slowly..."); +// thread::sleep(Duration::from_secs(2)); +// num +// }); +// +// if intensity < 25 { +// println!( +// "Today, do {} pushups!", +// expensive_result.value(intensity) +// ); +// println!( +// "Next, do {} situps!", +// expensive_result.value(intensity) +// ); +// } +// else { +// if random_number == 3 { +// println!("Take a break today! Remember to stay hydrated!"); +// } +// else { +// println!( +// "Today, run for {} minutes!", +// expensive_result.value(intensity) +// ); +// } +// } +//} +// + + -struct Cacher - where T: Fn(u32) -> u32 -{ - calculation: T, - value: Option, -} fn main() { - let simulated_user_specified_value = 10; - let simulated_random_number = 7; + let v1 = vec![1, 2, 3]; + let v1_iter = v1.iter(); + + for val in v1_iter { + dbg!(val); + } +} + +#[test] +fn iterator_demonstration() { + let v1 = vec![1, 2, 3]; + let mut v1_iter = v1.iter(); + + assert_eq!(v1_iter.next(), Some(&1)); + assert_eq!(v1_iter.next(), Some(&2)); + assert_eq!(v1_iter.next(), Some(&3)); + assert_eq!(v1_iter.next(), None); +} + +#[test] +fn iterator_sum() { + let v1 = vec![1, 2, 3]; + let v1_iter = v1.iter(); + let total: i32 = v1_iter.sum(); + assert_eq!(total, 6); +} + +#[test] +fn iterator_map() { + let v1: Vec = vec![1, 2, 3]; + let v2: Vec<_> = v1.iter().map(|x| x + 1).collect(); + assert_eq!(v2, vec![2, 3, 4]); +} + + - generate_workout( - simulated_user_specified_value, - simulated_random_number +#[derive(PartialEq, Debug)] +struct Shoe { + size: i32, + style: String, +} + +fn shoes_in_my_size(shoes: Vec, shoe_size: i32) -> Vec { + shoes.into_iter() + .filter(|s| s.size == shoe_size) + .collect() +} + +#[test] +fn filters_by_size() { + let shoes = vec![ + Shoe { size: 10, style: String::from("sneaker") }, + Shoe { size: 10, style: String::from("boot") }, + Shoe { size: 13, style: String::from("sandal") }, + ]; + + let in_my_size = shoes_in_my_size(shoes, 10); + + assert_eq!( + in_my_size, + vec![ + Shoe { size: 10, style: String::from("sneaker") }, + Shoe { size: 10, style: String::from("boot") }, + ] ); } -fn generate_workout(intensity: u32, random_number: u32) { - let expensive_closure = |num| { - println!("calculating slowly..."); - thread::sleep(Duration::from_secs(2)); - num - }; - - if intensity < 25 { - println!( - "Today, do {} pushups!", - expensive_closure(intensity) - ); - println!( - "Next, do {} situps!", - expensive_closure(intensity) - ); +struct Counter { + count: u32, +} + +impl Counter { + fn new() -> Counter { + Counter { count: 0 } } - else { - if random_number == 3 { - println!("Take a break today! Remember to stay hydrated!"); +} + +impl Iterator for Counter { + type Item = u32; + + fn next(&mut self) -> Option { + self.count += 1; + + if self.count < 6 { + Some(self.count) } else { - println!( - "Today, run for {} minutes!", - expensive_closure(intensity) - ); + None } } } +#[test] +fn calling_next_directly() { + let mut counter = Counter::new(); + assert_eq!(counter.next(), Some(1)); + assert_eq!(counter.next(), Some(2)); + assert_eq!(counter.next(), Some(3)); + assert_eq!(counter.next(), Some(4)); + assert_eq!(counter.next(), Some(5)); + assert_eq!(counter.next(), None); +} + +#[test] +fn using_other_iterator_trait_methods() { + let sum: u32 = Counter::new().zip(Counter::new().skip(1)) + .map(|(a, b)| a * b) + .filter(|x| x % 3 == 0) + .sum(); + assert_eq!(18, sum); +} diff --git a/minigrep/Cargo.toml b/minigrep/Cargo.toml index 6a8174c..09021c1 100644 --- a/minigrep/Cargo.toml +++ b/minigrep/Cargo.toml @@ -5,3 +5,4 @@ authors = ["Adam Carpenter <53hornet@gmail.com>"] edition = "2018" [dependencies] + diff --git a/minigrep/src/lib.rs b/minigrep/src/lib.rs index bf7118f..bb8b4d7 100644 --- a/minigrep/src/lib.rs +++ b/minigrep/src/lib.rs @@ -10,26 +10,20 @@ pub struct Config { impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(mut args: std::env::Args) -> Result { + args.next(); - if args.len() < 3 { - return Err("Not enough arguments."); - } + let query = match args.next() { + Some(arg) => arg, + None => return Err("Didn't get a query string"), + }; - let query = args[1].clone(); - let filename = args[2].clone(); - let mut case_sensitive = env::var("CASE_INSENSITIVE").is_err(); - - // override environment variable if cli arg is present - if args.len() > 3 { - if args[3] == "-s" { - case_sensitive = true; - } - else if args[3] == "-i" { - case_sensitive = false; - } - } + let filename = match args.next() { + Some(arg) => arg, + None => return Err("Didn't get a filename"), + }; + let case_sensitive = env::var("CASE_INSENSITIVE").is_err(); Ok(Config { query, filename, case_sensitive }) } @@ -54,28 +48,16 @@ pub fn run(config: Config) -> Result<(), Box> { } fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { - let mut results = Vec::new(); - - for line in contents.lines() { - if line.contains(query) { - results.push(line); - } - } - - results + contents.lines() + .filter(|line| line.contains(query)) + .collect() } fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { - let query = query.to_lowercase(); - let mut results = Vec::new(); - - for line in contents.lines() { - if line.to_lowercase().contains(&query) { - results.push(line); - } - } - - results + contents.lines() + .filter(|line| line.to_lowercase() + .contains(&query.to_lowercase())) + .collect() } #[cfg(test)] diff --git a/minigrep/src/main.rs b/minigrep/src/main.rs index 3cec101..c752da1 100644 --- a/minigrep/src/main.rs +++ b/minigrep/src/main.rs @@ -5,8 +5,7 @@ use minigrep; use minigrep::Config; fn main() { - let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { + let config = Config::new(env::args()).unwrap_or_else(|err| { eprintln!("Problem parsing arguments: {}", err); process::exit(1); }); -- cgit v1.2.3