アプリユーザの年齢や、 BMI、運動の好み、最近のトレーニング、指定された強弱値などの多くの要因からトレーニングプランを生成するアルゴリズムあるとします。
use std::thread; use std::time::Duration; // 重い計算と仮定する fn simulated_expensive_calculation(intensity: u32) -> u32 { // ゆっくり計算します println!("calculating slowly..."); thread::sleep(Duration::from_secs(2)); intensity }
fn main() { // 簡潔にするために一部ハードコード // ハードコードされたユーザー入力の強弱値 let simulated_user_specified_value = 10; // ハードコードされたランダム値(rand) let simulated_random_number = 7; generate_workout( simulated_user_specified_value, simulated_random_number ); }
fn generate_workout(intensity: u32, random_number: u32) { if intensity < 25 { println!( // 今日は{}回腕立て伏せをしてください! "Today, do {} pushups!", simulated_expensive_calculation(intensity) ); println!( // 次に、{}回腹筋をしてください! "Next, do {} situps!", simulated_expensive_calculation(intensity) ); } else { if random_number == 3 { // 今日は休憩してください!水分補給を忘れずに! println!("Take a break today! Remember to stay hydrated!"); } else { println!( // 今日は、{}分間走ってください! "Today, run for {} minutes!", simulated_expensive_calculation(intensity) ); } } }
// 重複削除して一つにする fn generate_workout(intensity: u32, random_number: u32) { let expensive_result = simulated_expensive_calculation(intensity); if intensity < 25 { println!( "Today, do {} pushups!", expensive_result ); println!( "Next, do {} situps!", expensive_result ); } else { if random_number == 3 { println!("Take a break today! Remember to stay hydrated!"); } else { println!( "Today, run for {} minutes!", expensive_result ); } } }
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)//-> 同じクロージャ1 ); println!( "Next, do {} situps!", expensive_closure(intensity)//-> 同じクロージャ2 ); } else { if random_number == 3 { println!("Take a break today! Remember to stay hydrated!"); } else { println!( "Today, run for {} minutes!", expensive_closure(intensity) ); } } }
let expensive_closure = |num: u32| -> u32 { println!("calculating slowly..."); thread::sleep(Duration::from_secs(2)); num };
fn add_one_v1 (x: u32) -> u32 { x + 1 } let add_one_v2 = |x: u32| -> u32 { x + 1 }; let add_one_v3 = |x| { x + 1 }; let add_one_v4 = |x| x + 1 ;
let example_closure = |x| x; let s = example_closure(String::from("hello")); let n = example_closure(5);
error[E0308]: mismatched types --> src/main.rs | | let n = example_closure(5); | ^ expected struct `std::string::String`, found integral variable | = note: expected type `std::string::String` found type `{integer}`
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 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) ); } } }
#[test] fn call_with_different_values() { let mut c = Cacher::new(|a| a); let v1 = c.value(1); let v2 = c.value(2); assert_eq!(v2, 2); }
thread 'call_with_different_values' panicked at 'assertion failed: `(left == right)` left: `1`, right: `2`', src/main.rs
let v1 = vec![1, 2, 3]; let v1_iter = v1.iter(); for val in v1_iter { // {}でした println!("Got: {}", val); }
pub trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; // デフォルト実装のあるメソッドは省略 // methods with default implementations elided }
[](Iteratorトレイトを実装するには、Item型も定義する必要があり、 そして、このItem型がnextメソッドの戻り値の型に使われている。type, Self::Itemは、関連型についての詳細は、第19章)
#[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); }
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]);
#[derive(PartialEq, Debug)] struct Shoe { size: u32, style: String, } fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> 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: 13, style: String::from("sandal") }, Shoe { size: 10, style: String::from("boot") }, ]; 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") }, ] ); }
struct Counter { count: u32, } impl Counter { fn new() -> Counter { Counter { count: 0 } } } // イテレータを使用したときに起きてほしいことを書く 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 { None } } }
impl Config { pub fn new(args: &[String]) -> Result<Config, &'static str> { if args.len() < 3 { return Err("not enough arguments"); } // ここが問題で非効率 マジックナンバーだしね。。。 let query = args[1].clone(); let filename = args[2].clone(); // ここ追加してる? let case_sensitive = env::var("CASE_INSENSITIVE").is_err(); Ok(Config { query, filename, case_sensitive }) } }
fn main() { let args: Vec<String> = env::args().collect(); let config = Config::new(&args).unwrap_or_else(|err| { eprintln!("Problem parsing arguments: {}", err); process::exit(1); }); // --snip-- }
↓
fn main() { let config = Config::new(env::args()).unwrap_or_else(|err| { eprintln!("Problem parsing arguments: {}", err); process::exit(1); }); // --snip-- }
impl Config { pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> {
impl Config { pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> { args.next(); let query = match args.next() { Some(arg) => arg, // クエリ文字列を取得しませんでした None => return Err("Didn't get a query string"), }; let filename = match args.next() { Some(arg) => arg, // ファイル名を取得しませんでした None => return Err("Didn't get a file name"), }; let case_sensitive = env::var("CASE_INSENSITIVE").is_err(); Ok(Config { query, filename, case_sensitive }) } }
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { contents.lines() .filter(|line| line.contains(query)) .collect() }
test bench_search_for ... bench: 19,620,300 ns/iter (+/- 915,700) test bench_search_iter ... bench: 19,234,900 ns/iter (+/- 657,200)