Release Channels
https://doc.rust-lang.org/book/release-channels.html
Rustは
- Nightly
- Beta
- Stable
の3種類がある。
Betaは6週間間隔でバージョンが上がるプロセスが出来上がっているみたい。リリースマネジメント(?)が着実に行われている。
Borrow and AsRef
https://doc.rust-lang.org/book/borrow-and-asref.html
Borrow
とAsRef
について。
サンプルコードを動かしてみた。
use std::borrow::Borrow; use std::fmt::Display; fn foo<T: Borrow<i32> + Display>(a: T) { println!("a is borrowed: {}", a); } fn bar<T: AsRef<str>>(s: T) { let mut slice = s.as_ref(); println!("{}", slice); } fn main() { let mut i = 5; foo(&i); foo(&mut i); let s = "Hello".to_string(); bar(s); }
$ cargo run Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/5_10_borrow_and_asref` a is borrowed: 5 a is borrowed: 5 Hello
FFI
https://doc.rust-lang.org/book/ffi.html
他言語で記載されたライブラリをRustから使うための方法。ライブラリのパスをさくっと通せなかったので、動かしてみるのをあきらめた。
Choosing your Guarantees
https://doc.rust-lang.org/book/choosing-your-guarantees.html
Guaranteesは保証という意味の単語らしい。
use std::cell::Cell; use std::cell::RefCell; fn main() { let x = Cell::new(1); let y = &x; let z = &x; x.set(2); y.set(3); z.set(4); println!("{}", x.get()); let x = RefCell::new(vec![1,2,3,4]); { println!("{:?}", *x.borrow()) } { let mut my_ref = x.borrow_mut(); my_ref.push(1); } }
$ cargo run Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/5_8_choosing_your_guarantees` 4 [1, 2, 3, 4]
Error Handling #10
https://doc.rust-lang.org/book/error-handling.html
サンプルの'‘city-pop’‘を最後まで。
extern crate getopts; extern crate rustc_serialize; extern crate csv; use getopts::Options; use std::env; use std::fs::File; use std::path::Path; use std::error::Error; use std::io; use std::process; #[derive(Debug)] enum CliError { Io(io::Error), Csv(csv::Error), NotFound, } use std::fmt; impl fmt::Display for CliError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { CliError::Io(ref err) => err.fmt(f), CliError::Csv(ref err) => err.fmt(f), CliError::NotFound => write!(f, "No matching cities with a \ population were found."), } } } impl Error for CliError { fn description(&self) -> &str { match *self { CliError::Io(ref err) => err.description(), CliError::Csv(ref err) => err.description(), CliError::NotFound => "not found", } } fn cause(&self) -> Option<&Error> { match *self { CliError::Io(ref err) => Some(err), CliError::Csv(ref err) => Some(err), // Our custom error doesn't have an underlying cause, // but we could modify it so that it does. CliError::NotFound => None, } } } impl From<io::Error> for CliError { fn from(err: io::Error) -> CliError { CliError::Io(err) } } impl From<csv::Error> for CliError { fn from(err: csv::Error) -> CliError { CliError::Csv(err) } } // This struct represents the data in each row of the CSV file. // Type based decoding absolves us of a lot of the nitty gritty error // handling, like parsing strings as integers or floats. #[derive(Debug, RustcDecodable)] struct Row { country: String, city: String, accent_city: String, region: String, // Not every row has data for the population, latitude or longitude! // So we express them as `Option` types, which admits the possibility of // absence. The CSV parser will fill in the correct value for us. population: Option<u64>, latitude: Option<f64>, longitude: Option<f64>, } struct PopulationCount { city: String, country: String, // This is no longer an `Option` because values of this type are only // constructed if they have a population count. count: u64, } fn print_usage(program: &str, opts: Options) { println!("{}", opts.usage(&format!("Usage: {} [options] <city>", program))); } fn search<P: AsRef<Path>> (file_path: &Option<P>, city: &str) -> Result<Vec<PopulationCount>, CliError> { let mut found = vec![]; let input: Box<io::Read> = match *file_path { None => Box::new(io::stdin()), Some(ref file_path) => Box::new(try!(File::open(file_path))), }; let mut rdr = csv::Reader::from_reader(input); for row in rdr.decode::<Row>() { let row = try!(row); match row.population { None => { } // Skip it. Some(count) => if row.city == city { found.push(PopulationCount { city: row.city, country: row.country, count: count, }); }, } } if found.is_empty() { Err(CliError::NotFound) } else { Ok(found) } } fn main() { let args: Vec<String> = env::args().collect(); let program = &args[0]; let mut opts = Options::new(); opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME"); opts.optflag("h", "help", "Show this usage message."); opts.optflag("q", "quiet", "Silences errors and warnings."); // ... let matches = match opts.parse(&args[1..]) { Ok(m) => { m } Err(e) => { panic!(e.to_string()) } }; if matches.opt_present("h") { print_usage(&program, opts); return; } let data_path = matches.opt_str("f"); let city = if !matches.free.is_empty() { &matches.free[0] } else { print_usage(&program, opts); return; }; match search(&data_path, city) { Err(CliError::NotFound) if matches.opt_present("q") => process::exit(1), Err(err) => panic!("{}", err), Ok(pops) => for pop in pops { println!("{}, {}: {:?}", pop.city, pop.country, pop.count); } } }
Error Handling #9
https://doc.rust-lang.org/book/error-handling.html
今日は、Error handling with a custom typeの手前まで。
Error Handling #8
https://doc.rust-lang.org/book/error-handling.html
Reading from stdinの手前まででビルド通った。
extern crate getopts; extern crate rustc_serialize; extern crate csv; use getopts::Options; use std::env; use std::fs::File; use std::path::Path; use std::error::Error; // This struct represents the data in each row of the CSV file. // Type based decoding absolves us of a lot of the nitty gritty error // handling, like parsing strings as integers or floats. #[derive(Debug, RustcDecodable)] struct Row { country: String, city: String, accent_city: String, region: String, // Not every row has data for the population, latitude or longitude! // So we express them as `Option` types, which admits the possibility of // absence. The CSV parser will fill in the correct value for us. population: Option<u64>, latitude: Option<f64>, longitude: Option<f64>, } struct PopulationCount { city: String, country: String, // This is no longer an `Option` because values of this type are only // constructed if they have a population count. count: u64, } fn print_usage(program: &str, opts: Options) { println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>", program))); } fn search<P: AsRef<Path>> (file_path: P, city: &str) -> Result<Vec<PopulationCount>, Box<Error>> { let mut found = vec![]; let file = try!(File::open(file_path)); let mut rdr = csv::Reader::from_reader(file); for row in rdr.decode::<Row>() { let row = try!(row); match row.population { None => { } // Skip it. Some(count) => if row.city == city { found.push(PopulationCount { city: row.city, country: row.country, count: count, }); }, } } if found.is_empty() { Err(From::from("No matching cities with a population were found.")) } else { Ok(found) } } fn main() { let args: Vec<String> = env::args().collect(); let program = &args[0]; let mut opts = Options::new(); opts.optflag("h", "help", "Show this usage message."); let matches = match opts.parse(&args[1..]) { Ok(m) => { m } Err(e) => { panic!(e.to_string()) } }; if matches.opt_present("h") { print_usage(&program, opts); return; } let data_path = &matches.free[0]; let city: &str = &matches.free[1]; match search(data_path, city) { Ok(pops) => { for pop in pops { println!("{}, {}: {:?}", pop.city, pop.country, pop.count); } } Err(err) => println!("{}", err) } }