2018年 Rustチャレンジ
2018年に新しく学ぶ言語としてRustにチャレンジしてみる。
Rustのドキュメント(邦訳)を見ながら進める。
http://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/book/
ドキュメントの本家はこっち。
https://doc.rust-lang.org/book/
環境構築
Rustの開発ツールはHomebrewで簡単にインストールできる。
rustc
やcargo
といったコマンドがインストールされる。
$ brew install rust
新規プロジェクト作成
Cargoを利用してプロジェクトを作成する。
バイナリを作成するため--bin
オプションをつける。
$ cargo new rustlang-intro --bin $ cd rustlang-intro/ $ cargo build $ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/rustlang-intro` Hello, world!
リリースビルドをするには--release
オプションをつける。
すると、target/release
の下に成果物が作成される。
$ cargo build --release
標準入力
標準入力で受けた文字列を標準エラー出力に表示する。
use std::io; fn print_stdin() { let mut line = String::new(); let _ = io::stdin().read_line(&mut line); eprintln!("{}", line.trim()); }
乱数生成
rand
クレートを利用して乱数を生成・表示する。
まず、Cargo.toml
に依存関係を記述する。
[dependencies] rand = "0.4.1"
10回乱数を生成して表示する。
extern crate rand; fn print_random_numbers() { for _ in 0..10 { let n = rand::random::<i32>(); println!("{}", n) } }
こう書くこともできる。
extern crate rand; use rand::Rng; fn print_random_numbers() { let mut rng = rand::thread_rng(); for _ in 0..10 { let n = rng.gen::<i32>(); println!("{}", n) } }
構造体
構造体を作る。メソッド実装にはimpl
ブロックを利用する。
new
メソッドで構造体初期化を行なっているが、メソッド名は慣習でしかなく、名前はなんでも良い。
また、このようにself
を引数に持たないメソッドは関連関数(associated function)と呼ばれるが、他の言語で言う静的メソッド(static method)に該当するものと思っておけば良い。
struct Person { name: String, } impl Person { fn new(name: &str) -> Person { Person { name: name.to_string(), } } fn get_name(&self) -> &String { &self.name } } fn main() { let p = Person::new("person's name"); println!("{}", p.get_name()); }
ちなみに、以下のようなコードを書いてしまうとエラーになる。
借り物(self
)から勝手に所有権をmoveできないということ。
上のコードのように参照で返すようにしなければコンパイルが通らない。
fn get_name(&self) -> String { self.name }
error[E0507]: cannot move out of borrowed content --> src/main.rs:33:9 | 33 | self.name | ^^^^ cannot move out of borrowed content
トレイト
trait Hello { fn say(&self); } impl Hello for Person { fn say(&self) { println!("Hello {}", self.name); } } fn main() { let h = Person::new("trait"); h.say(); }
マクロ
引数なし版と引数あり版の簡単なものを作ってみる。
macro_rules! say_hello { () => { println!("Hello"); }; ($x:expr) => { println!("Hello {}", $x); }; } fn main() { say_hello!(); say_hello!("name"); }
テスト
テストを書いてみる。
慣習的にテストコードを入れる専用のモジュールを作っておくらしい。cargo test
のときだけコンパイルされる条件付きコンパイルのフラグをつけておく。
fn add(x: i64, y: i64) -> i64 { return x + y; } #[cfg(test)] mod tests { use super::*; #[test] fn test_add() { assert_eq!(10, add(4, 6)); } }
$ cargo test ...(中略)... running 1 test test tests::test_add ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
まとめ
環境構築から基本的な記述まで試すことができた。
借用の概念がまだ自分の中で綺麗に整理できていないのでもう少し資料を漁りながら試してみることにする。
今度はマルチスレッドでHTTPサーバでも実装してみる。