百鬼夜行

素性を知られぬままエンジニアになることを目指します

「The Book」で Rust 入門 2 前半

前回のあらすじ

yagyosan.hatenablog.com

数当てゲームをプログラムする

Rustの基礎となる要素について学ぶ。同じようにCargoでプロジェクトを生成した後、まずは自分が入力した数値を出力するプログラムを書く。

予測を処理する

use std::io;

fn main() {
    println!("Guess the number!");

    println!("Please input your guess.");

    let mut guress = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line");

    println!("your gessed: {}", guess);
}
  • use std::io; : 標準ライブラリstdのio(入/出力)ライブラリをスコープに導入する
  • デフォルトでは、preludeに存在するいくつかの型のみ使える
    • 使用したい型がpreludeにない場合は、use文で明示的にその型をスコープに導入する必要がある
  • let: 変数の作成(変数は標準でイミュータブル)
  • mut: 可変変数にするための装飾子
  • String::new: Stringを返す関数で、::は関連関数であることを示す
    • 関連関数: 特定のオブジェクトよりも型(この場合はString)に対して実装された関数のことで、静的メソッドと呼ばれる言語もある
  • io::stdin(): std::io::Stdin オブジェクト(=標準入力へのハンドル)を返す関数で、この記述ができるのは行頭でライブラリをスコープに導入したため
  • .read_line(&mut guess): ユーザが標準入力したものすべてを取り出して、文字列に格納する(格納する文字列を引数にとる)
    • io::Result型を返す
    • &mut guess: 格納する時に文字列を変更できるよう可変変数にする
    • &: 引数が参照であることを表し、データを複数回メモリにコピーせずとも、 コードの複数箇所で同じデータにアクセスできる(これもいミュータブル)
  • Result型: 固定された種類の値を持つ型(enum
    • 型のvariant(取りうる値は)がOk列挙子とErr列挙子
  • .expect("Failed to read line");: Err値だった場合プログラムをクラッシュさせ、 引数として渡されたメッセージを表示する
    • 警告を抑制する正しい手段は後で
  • println!("You guessed: {}", guess);: {}は値を所定の場所に保持するもので、一つ以上の値を出力できる

ひとまずこれで出力までできるようになった。

秘密の数字を生成する

ゲームを実行するたびにランダムで秘密の数字が生成されるようにする。

  • クレート: Rustコードのパッケージ、バイナリークレートとライブラリクレートがある
    • バイナリークレート: 実行可能ファイル
    • ライブラリクレート: 他のプログラムで使用するためのコード

まずはCargo.toml[dependencies]randクレートを追加し、ビルドする。

$ cargo build
   Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling libc v0.2.43                                                       
   Compiling rand v0.4.3
   Compiling rand v0.3.22
   Compiling guessing_game v0.1.0 (file:///Users/yagyosan/Develop/rust_study/guessing_game)
   Finished dev [unoptimized + debuginfo] target(s) in 1m 09s
  • SemVer: バージョンナンバー記述の標準規格
  • Creates.ioにRustのOSSプロジェクトがあり、リポジトリからクレートを引っ張ってこれる
  • Cargo.lock: 明示的にクレートの記述を変更しない限り、 プロジェクトが使用するバージョンを保ってくれる
  • cargo update: クレートのバージョンを更新するが、標準で0.4.0未満のものだけを検索するようになっている

これでクレートが使えるようになったので、ランダムな数値の生成を試みる。

extern crate rand;

use std::io;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line");

    println!("your gessed: {}", guess);
}
  • extern crate rand;: 外部依存として使用することを知らせる行(use randと同じ効果)
  • use rand::Rng;: Rngトレイト(後ほど解説)は乱数生成器が実装するメソッドを定義していて、 このトレイトがスコープにないと、メソッドを使用できない
  • rand::thread_rng(): これから使う特定の乱数生成器を返す
    • .gen_range(1, 101);: 二つの数字を引数間の乱数を生成してくれる
  • cargo doc --open 依存するクレートのマニュアルをビルドしてくれる

続きはまた今度。