summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Carpenter <53hornet@gmail.com>2019-03-01 14:01:17 -0500
committerAdam Carpenter <53hornet@gmail.com>2019-03-01 14:01:17 -0500
commitb71e253b697bae079a0cf2526209334f4b81f9a5 (patch)
tree0251289af1860305903760f719821593a672ed39
parentdb0289b1813b73a93c22f12379ba501dbadc7552 (diff)
downloadlearning-rust-b71e253b697bae079a0cf2526209334f4b81f9a5.tar.xz
learning-rust-b71e253b697bae079a0cf2526209334f4b81f9a5.zip
Added functional and implemented iterators in minigrep.
-rw-r--r--functional/src/main.rs210
-rw-r--r--minigrep/Cargo.toml1
-rw-r--r--minigrep/src/lib.rs54
-rw-r--r--minigrep/src/main.rs3
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<T>
+// where T: Fn(u32) -> u32
+//{
+// calculation: T,
+// value: Option<u32>,
+//}
+//
+//impl<T> Cacher<T>
+// where T: Fn(u32) -> u32
+//{
+// fn new (calculation: T) -> Cacher<T> {
+// 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<T>
- where T: Fn(u32) -> u32
-{
- calculation: T,
- value: Option<u32>,
-}
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<i32> = 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>, shoe_size: i32) -> Vec<Shoe> {
+ 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::Item> {
+ 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<Config, &'static str> {
+ pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> {
+ 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<dyn Error>> {
}
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<String> = 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);
});