Error Handling #5
https://doc.rust-lang.org/book/error-handling.html
ファイル処理の異常処理の続き。エラーの時の処理が明示的になってきたように思う。
use std::fs::File; use std::io::Read; use std::path::Path; fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> { let mut file = match File::open(file_path) { Ok(file) => file, Err(err) => return Err(err.to_string()), }; let mut contents = String::new(); if let Err(err) = file.read_to_string(&mut contents) { return Err(err.to_string()); } let n: i32 = match contents.trim().parse() { Ok(n) => n, Err(err) => return Err(err.to_string()), }; Ok(2 * n) } fn main() { match file_double("foobar") { Ok(n) => println!("{}", n), Err(err) => println!("Error: {}", err), } }
Error Handling #4
https://doc.rust-lang.org/book/error-handling.html
use std::fs::File; use std::io::Read; use std::path::Path; fn file_double<P: AsRef<Path>>(file_path: P) -> i32 { let mut file = File::open(file_path).unwrap(); // error 1 let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); // error 2 let n: i32 = contents.trim().parse().unwrap(); // error 3 2 * n } fn main() { let doubled = file_double("foobar"); println!("{}", doubled); }
$ cargo run Compiling 5_7_error_handling v0.1.0 (file:///Users/miura/work/git-work/exercises/The_Rust_Programming_Language/5_7_error_handling) Finished debug [unoptimized + debuginfo] target(s) in 1.38 secs Running `target/debug/5_7_error_handling` thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { repr: Os { code: 2, message: "No such file or directory" } }', ../src/libcore/result.rs:837 note: Run with `RUST_BACKTRACE=1` for a backtrace. $ touch foobar $ cargo run Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/5_7_error_handling` thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: Empty }', ../src/libcore/result.rs:837 note: Run with `RUST_BACKTRACE=1` for a backtrace. $ echo 1 > foobar (anaconda3-4.2.0) miura (master *) 5_7_error_handling $ cargo run Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/5_7_error_handling` 2
Error Handling #3
https://doc.rust-lang.org/book/error-handling.html
use std::env;
すると、argv.nth
で引数をとれる。
引数の有無でエラー判定するための方法。
use std::env; fn ok_or<T, E>(option: Option<T>, err: E) -> Result<T, E> { match option { Some(val) => Ok(val), None => Err(err), } } fn double_arg(mut argv: env::Args) -> Result<i32, String> { argv.nth(1) .ok_or("Please give at least one argument".to_owned()) .and_then(|arg| arg.parse::<i32>().map_err(|err| err.to_string())) .map(|n| 2 * n) } fn main() { match double_arg(env::args()) { Ok(n) => println!("{}", n), Err(err) => println!("Error: {}", err), } }
$ cargo run Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/5_7_error_handling` Error: Please give at least one argument $ cargo run a Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/5_7_error_handling a` Error: invalid digit found in string $ cargo run 3 Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/5_7_error_handling 3` 6
Error Handling #2
https://doc.rust-lang.org/book/error-handling.html
文字列を整数にパースするときのエラーハンドリング。
use std::num::ParseIntError; fn double_number(number_str: &str) -> Result<i32, ParseIntError> { number_str.parse::<i32>().map(|n| 2 * n) } fn main() { match double_number("10") { Ok(n) => assert_eq!(n, 20), Err(err) => println!("Error: {:?}", err), } match double_number("a") { Ok(n) => assert_eq!(n, 20), Err(err) => println!("Error: {:?}", err), } }
$ cargo run Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/5_7_error_handling` Error: ParseIntError { kind: InvalidDigit }
Error Handling
https://doc.rust-lang.org/book/error-handling.html
とても長い。基本はpanic!
マクロを使ってエラーを発生させるということらしい。
Concurrency #2
https://doc.rust-lang.org/book/concurrency.html
並行処理続き。channelについて。rx
からtx
にデータが渡るまで、tx
側は処理を待つ。
use std::thread; use std::sync::mpsc; fn main() { let (tx, rx) = mpsc::channel(); for i in 0..10 { let tx = tx.clone(); thread::spawn(move || { let answer = i * i; tx.send(answer).unwrap(); }); } for _ in 0..10 { println!("{}", rx.recv().unwrap()); } let handle = thread::spawn(move || { panic!("oops!"); }); let result = handle.join(); assert!(result.is_err()); }
$ cargo run Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/5_6_concurrency` 0 1 4 16 25 9 64 36 81 49 thread '<unnamed>' panicked at 'oops!', src/main.rs:22 note: Run with `RUST_BACKTRACE=1` for a backtrace.
Concurrency
https://doc.rust-lang.org/book/concurrency.html
並列処理について。
use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; fn main() { let data = Arc::new(Mutex::new(vec![1, 2, 3])); for i in 0..3 { let data = data.clone(); thread::spawn(move || { let mut data = data.lock().unwrap(); data[0] += i; }); } thread::sleep(Duration::from_millis(50)); println!("{:?}", data); }
$ cargo run Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/5_6_concurrency` Mutex { data: [4, 2, 3] }