1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Re:ゼロから始めて rust を完全に理解する その1 

Last updated at Posted at 2019-07-03

ここを見て0からrustを勉強し始めた

https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/README.html
予備知識として、ワイC言語10年くらいやってて、ここ5年くらいはphp、pythonあたりをメインに触っとる程度を前提に書くンゴ。

インストールまで完全に理解した

割愛。
アホでもできる。

3.1. 数当てゲーム 完全に理解した

https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/guessing-game.html
↑こいつを見ていく

まずはプロジェクト作成、余裕、完全に理解した。

$ cargo new guessing_game --bin
$ cd guessing_game

外部クレート(パッケージ)を使用するのでCargo.tomlに追記

dependencies に randを追記、バージョンを現時点最新のを指定してみた。

[dependencies]

rand="0.4.6"

まずはソースの完成形、完全に理解したわ

extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

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

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

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

        let mut guess = String::new();

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

        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

        println!("You guessed: {}", guess);

        match guess.cmp(&secret_number) {
            Ordering::Less    => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal   => {
                println!("You win!");
                break;
            }
        }
    }
}

ソース、ちょい掘り下げて

外部クレートのrandを使えるようにする明示的宣言、Cの外部関数extern宣言と同じような意味合い。
externしなくても use rand::Rng があればコンパイル通る

extern crate rand;

!が付いてるのは関数じゃなくマクロ

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

let 変数束縛を作る。他言語と一番の違うのがこの辺、ここさえ乗り切ればrust完全に理解できると思う。
変数束縛とか言って、変数名に対して値を束縛する、とか言って所有権という概念が生まれる。
rustの言語の仕様として「Rustは与えられたリソースに対する束縛が 1つだけ あるということを保証する」

んで、変数束縛定義にmutを付けない場合、イミュータブルとか言って書き換え不可の定数になる。
gen_range(1, 101);は数値型を返され、secret_numberという変数に1~100の乱数が入る、
secret_numberがある数値を束縛する、secret_numberがこの乱数のリソースの所有権を持つ。

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

書き換え可能な変数作成は明示的にmutを付ける必要がある、ミュータブルとか言うやつ。
let mut guess = String::new(); の場合、guessという名前の変数にはString型のデータが入る。
String型にはポインタが含まれる、ので、この guess を別の変数に代入した場合、
guessとその別の変数はそれぞれ、同じアドレスを参照するポインタを持つことになるので、
同じリソースに対する束縛が同時に二つ存在することになる。
「Rustは与えられたリソースに対する束縛が 1つだけ あるということを保証する」ので、guess所有権が別の変数に渡され、
guess に対するアクセスができなくなる。
 let aaa = guess;
println!("{}", guess); <= ここでコンパイルエラーになる。

let mut guess = String::new();

stdinのread_lineで入力された文字列をguessに入れる。この辺は直感的に理解できるが、
read_line(&mut guess) 見慣れない。read_lineの引数が&mut参照型なのでこうやって渡す必要がある。
ミュータブルの参照型で、参照先で変数を書き換え可能になる。
かつ、&を付けて参照で渡していると、所有権を渡すのではなく、借用することになる、スコープから外れると所有権が自動で元の束縛に戻る。
なので、read_line(&mut guess) でguessが束縛しているリソースをread_lineに借用、read_lineから抜けると自動的にguessに所有権が戻る。
上記④のようなコンパイルエラーが起きなくなる。

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

長くなったので一旦区切り

続く。

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?