はじめに
こんばんは。
花粉症辛くて、頭ぼーっとしてます。
先日CODEPREPの記事を上げたのですが、twitterで返事がありました。
紹介ありがとうございます!ちなみに9月30日まで無償期間を延長してます。https://t.co/bWCgCTxJWZ
— mitsuruog (@mitsuruog) 2018年3月22日
無償提供期間は、9/30まで延長してくれているようです。
素晴らしい!ということで、せっかくなので、CODEPREPで紹介されていたRustを触ってみました。
やってみた
まずRust落としてみます。
CODEPREPの内容も、記載しますが、基本はコチラのRustの和訳を見ながら進めます。
ちなみに、この和訳はRsut 1.6の時に書かれたもののようで、現在Rustのバージョンは1.24.です。なので、少し内容的に古いものということは前提になります。
install
brewコマンドで落としました。
$ brew install rust ==> Downloading https://homebrew.bintray.com/bottles/libssh2-1.8.0.high_sierra.bottle.1.tar.gz ######################################################################## 100.0% ==> Pouring libssh2-1.8.0.high_sierra.bottle.1.tar.gz 🍺 /usr/local/Cellar/libssh2/1.8.0: 182 files, 797.4KB ==> Installing rust ==> Downloading https://homebrew.bintray.com/bottles/rust-1.24.1.high_sierra.bottle.tar.gz ######################################################################## 100.0% ==> Pouring rust-1.24.1.high_sierra.bottle.tar.gz 🍺 /usr/local/Cellar/rust/1.24.1: 6,033 files, 401.8MB
rustをインストールすると、一緒にcargoというツールもインストールされます。
cargoはrustをビルドしてくれるものでもあり、外部ライブラリを管理してくれるパッケージマネージャでもあるもののようです。
Composerみたいなもんかな?
$ cargo --version
cargo 0.25.0
プロジェクト作成
Cargoを使って、プロジェクトを作成できます。
$ cargo new sample01 --bin Created binary (application) `sample01` project $ tree sample01 sample01 ├── Cargo.toml └── src └── main.rs 1 directory, 2 files
数当てゲーム
コチラで紹介されている、数あてゲームを作ってみます。
1. src/main.rsを作成
※ Cargoでビルドするには、srcディレクトリ以下にソース群がないとエラーになります。
use std::io; fn main() { println!("数字を当ててみて!"); println!("予想地を入力してください。"); let mut guess = String::new(); io::stdin().read_line(&mut guess) .expect("行の読み取りに失敗しました。"); println!("あなたの予想値: {}", guess); }
一旦動かしてみます。
$ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/sample01` 数字を当ててみて! 予想地を入力してください。 10 あなたの予想値: 10
動いてました。
2. randクレートをインストール
クレートというのは、Rustのパッケージの意味のようです。
要は外部ライブラリをインストールするという感じですね。
Composer install的な感じかと。
Cargo.tomlのdependencies部分を以下のように修正します。
[dependencies] rand="0.3.0"
その後一旦ビルドします。
$ cargo build Updating registry `https://github.com/rust-lang/crates.io-index` Compiling libc v0.2.39 Compiling rand v0.4.2 Compiling rand v0.3.22 Compiling sample01 v0.1.0 (file:///path/to/sample01) Finished dev [unoptimized + debuginfo] target(s) in 3.8 secs
ちなみにtomlというファイルが気になったので調べてみると、コチラの記事を発見しました。
iniファイルっぽいので読みやすいし、他にもいろんな描き方できるの便利っぽいです。
phpでもパーサがあるっぽいんで、今度使ってみます。
3. src/main.rsを修正
extern crate rand; use std::io; use std::cmp::Ordering; use rand::Rng; fn main() { println!("数字を当ててみて!"); let secret_number = rand::thread_rng().gen_range(1, 101); println!("秘密の数字は: {}です", secret_number); println!("予想値を入力してください。"); let mut guess = String::new(); io::stdin().read_line(&mut guess) .expect("行の読み取りに失敗しました。"); let guess: u32 = guess.trim().parse() .expect("文字を入力してください。"); println!("あなたの予想値: {}", guess); match guess.cmp(&secret_number) { Ordering::Less => println!("小さすぎます!"), Ordering::Greater => println!("大きすぎます!"), Ordering::Equal => println!("あなたの勝ちです!"), } }
実行してみます。
$ cargo run Compiling sample01 v0.1.0 (file:///path/to/sample01) Finished dev [unoptimized + debuginfo] target(s) in 0.63 secs Running `target/debug/sample01` 数字を当ててみて! 秘密の数字は: 36です 予想値を入力してください。 10 あなたの予想値: 10 小さすぎます! $ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/sample01` 数字を当ててみて! 秘密の数字は: 35です 予想値を入力してください。 50 あなたの予想値: 50 大きすぎます! $ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/sample01` 数字を当ててみて! 秘密の数字は: 66です 予想値を入力してください。 66 あなたの予想値: 66 あなたの勝ちです!
なんとなくそれっぽいですね!
4. ゲームに勝つまでゲームが続くようにする。
extern crate rand; use std::io; use std::cmp::Ordering; use rand::Rng; fn main() { println!("数字を当ててみて!"); let secret_number = rand::thread_rng().gen_range(1, 101); loop { println!("予想値を入力してください。"); let mut guess = String::new(); io::stdin().read_line(&mut guess) .expect("行の読み取りに失敗しました。"); let guess: u32 = match guess.trim().parse() { Ok(num) => num, Err(_) => continue }; println!("あなたの予想値: {}", guess); match guess.cmp(&secret_number) { Ordering::Less => println!("小さすぎます!"), Ordering::Greater => println!("大きすぎます!"), Ordering::Equal => { println!("あなたの勝ちです!"); break; } } } }
実行します。
$ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running `target/debug/sample01` 数字を当ててみて! 予想値を入力してください。 20 あなたの予想値: 20 小さすぎます! 予想値を入力してください。 30 あなたの予想値: 30 小さすぎます! 予想値を入力してください。 40 あなたの予想値: 40 小さすぎます! 予想値を入力してください。 50 あなたの予想値: 50 大きすぎます! 予想値を入力してください。 45 あなたの予想値: 45 大きすぎます! 予想値を入力してください。 44 あなたの予想値: 44 大きすぎます! 予想値を入力してください。 43 あなたの予想値: 43 大きすぎます! 予想値を入力してください。 42 あなたの予想値: 42 あなたの勝ちです!
おーそれっぽいです!!
まとめ
今回CODEPREPで紹介されていたので触ってみたのですが、厳格な感じがphperの自分としては面白かったです。
あと、概念的に面白かったのが、所有権という機能でした。
そもそもRustの一押し機能?のようです。
まだ、キチンと説明できるほど、理解しているわけではないのですが、例えば、
fn main() { let test_1 = "Kojirock!".to_string(); let test_2 = test_1; println!("name = {}", test_1); }
とかってやって、runしてみるとエラー出ます。
$ cargo run Compiling sample02 v0.1.0 (file:///path/to/sample02) warning: unused variable: `test_2` --> src/main.rs:3:7 | 3 | let test_2 = test_1; | ^^^^^^ | = note: #[warn(unused_variables)] on by default = note: to avoid this warning, consider using `_test_2` instead error[E0382]: use of moved value: `test_1` --> src/main.rs:5:25 | 3 | let test_2 = test_1; | ------ value moved here 4 | 5 | println!("name = {}", test_1); | ^^^^^^ value used here after move | = note: move occurs because `test_1` has type `std::string::String`, which does not implement the `Copy` trait error: aborting due to previous error error: Could not compile `sample02`.
warningの方は使ってない変数 test_2
があるよってことなのですが、もう一つのほうが問題です。
use of moved value: `test_1`
イコールで代入した場合、そのデータ(リソース)の所有権が代入先に移り、代入元はアクセスできなくなってしまうということのようです。
これを所有権の移動(ムーブ)と言います。
おもしろい概念ですよね。
一回代入(変数の移動)したんなら、使わないよね?っていう潔さというか、清潔さというか。
回避策として、Copyトレイトとかを使用すればいいようです。
コンパイルエラー時の文章で書かれてますね。これも新設でわかりやすいです。
コピーといえば、ちょっと違いますがpythonのリストのコピーとかも少しにてますよね。
元のものを使いたい場合はcopyモジュール使いなさいよとか。
こう考えるとphpってやっぱりゆるくて、入りやすいってことなのかな。
終わりに
最近当初の勉強意欲がなくなってきているのを、感じまくっています。。。
テンションの停滞期とでも言うんでしょうか。
こういう時勉強を続けている人たちにも、大小あれ必ず訪れると思うんですが、その時の乗り越え方とかを教えてほしいです。
とりあえず僕の考えた乗り越え方は、簡単なことからやってく
ということです。
最近平日に1記事、土日に1記事という感じで進めてみようと思ってたんですが、早速この作戦が裏目に出ています。
土日はやはり子供と奥さんのために使わないと、家庭環境がギクシャクしてしまいます。
なので、来週からは、頑張って平日中に2記事仕上げようと思います。
なんか記事書くことが目標みたいですが、それでもいいんです。
今年1年はとりあえず、書くこと。
来年からは内容を充実させることを目標にしてるので。
では来週も頑張ります。
次は、Rustの所有権周りについて、勉強して記事に残しておこうと思います。