matobaの備忘録

育児しながら働くあるエンジニアの記録

Rustで標準入力を受け取って、標準出力に出してみただけの話

Rustで標準入力を受け取って、標準出力に出してみただけの記録を書きます。

以下の本を読んでいたら、こんなサンプルがありました。

数当てゲームをプログラムする - The Rust Programming Language 日本語版

use std::io;


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

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

    let mut guess = String::new();

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

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

このページは、解説を読みながら、自分なりの理解をメモしていきます。

ライブラリを読み込む

以下の行で、標準ライブラリstdの中に存在するioライブラリを読み込む。

use std::io;

関数を定義する

関数は以下で定義できる。

fn main() {
}

mainはエントリーポイントでもある。

fnで関数を表す。上記は引数や返り値を持たないが、持つケースは追々学べるハズ。

こんな風に構造化できる。

fn hello() {
    println!("hello");
}

fn main() {
    hello();
}

変数を宣言する

以下のようにして、変数を宣言できる。

let foo = 5;

ただし、このfooはimmutableになる。つまり、変更することができない。

以下のような関数があってコンパイルするとエラーが出る。

fn define_foo() {
    let foo = 5;

    foo = foo + 1;
    println!("foo: {}", foo);
}

エラー内容

 --> src/main.rs:6:5
  |
4 |     let foo = 5;
  |         ---
  |         |
  |         first assignment to `foo`
  |         help: make this binding mutable: `mut foo`
5 |
6 |     foo = foo + 1;
  |     ^^^^^^^^^^^^^ cannot assign twice to immutable variable

可変の変数を宣言したい場合は、mutをつける。

fn define_foo() {
    let mut foo = 5;

    foo = foo + 1;
    println!("foo: {}", foo);
}

これでコンパイルが通る。Rustでは変数は標準が不変らしい。

変数が標準で不変になっていると何が嬉しいのかは今のところよくわかっていない。

変数の型を束縛する

以下の行は、guessという変数にString型のオブジェクトのnew関数を呼び出した結果で束縛している。

let mut guess = String::new();

現時点では、「束縛する」という概念が何なのかはよくわかっていない。 とりあえず、その型しかいれられないようになるのかな、くらいのイメージで進む。

なお、Stringは標準ライブラリによって提供される文字列の型らしい。 newといういわゆるスタティックメソッドを持っている。Rustでは「関連関数」と呼ぶらしい。

読み込んだライブラリの関数を呼び出す

use std::io; で読み込んだioライブラリのstdin関数を呼び出す場合、以下のようになる。

io::stdin()

なお、 use std::io で事前に読み込んでいない場合、 次のように呼び出せるらしい。

std::io::stdin()

std::io::stdin() の返り値は std::io::Stdin というオブジェクトらしい。

オブジェクトのメソッドを呼び出す。

以下のように書くと、返ってきた std::io::Stdin に対してread_lineメソッドを呼び出せるらしい。

io::stdin().read_line(&mut guess)

&mut guess は変数として参照渡ししている。らしい。

guessって変数として定義したんじゃなかったっけ?とか思うけど、メソッドや関数に参照渡しして、書き換える時は、 mut が必要なのかな。 & が参照渡しを意味している様子。

今のところよくわかってないけど、関数とかメソッド呼び出しを学ぶときにもう少し詳しく知れるのだろう。

メソッドの処理結果を解釈する

io::stdin().read_line(&mut guess) を実行すると Result 型というものが返ってくるらしい。

Result側は、OkかErrらしい。

Rustでは、エラーが発生する可能性がある行で、エラーの際の処理を書いていないとコンパイル時に警告が発生するらしい。

io::stdin().read_line(&mut guess)
warning: unused `std::result::Result` that must be used
  --> src/main.rs:19:5
   |
19 |     io::stdin().read_line(&mut guess);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(unused_must_use)]` on by default
   = note: this `Result` may be an `Err` variant, which should be handled

エラーハンドリングするの忘れなくて良さげ。

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

ここでは、expectを書いて、わざとクラッシュさせているらしい。そのほかのハンドリングは追々学ぶ。

標準に入力に変数を埋め込む

printデバッグするために、変数を標準出力に出したいことはある。

そのときに使えそうな例。

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

説明は省略。

所感

とりあえず、標準入力を受け取って標準出力に出すサンプルを見つつ、勉強したことを記録した。

今のところ「へー。そうなんだー」という感じ。

この記事はわざわざ公開する必要もない内容を書いている。

Notionとか非公開のところに書けばいいと言う話もあるかもしれないけど、別に隠す話でもないのと、ブログなどを介して、「なんかやってる感」を出していきたかったり、自分の中で非公開状態のところにメモするより公開状態のところにメモする方が記憶に残るので、ブログに書いてみました。

まあ、気が向いたらRustについて学び進めていきます。