Charaken 技術系ブログ

技術系に関して学んだことや、気になったことを記事にしていく。

【Rust】がばがばRust独学 - 1. 変数と型

f:id:charaken:20191223210559p:plain

Rustの公式ドキュメントを通して、Rustを独学していく記事になります。(がば要素あり)

doc.rust-lang.org

今回は、変数と型について学びつつ、気になった点をコード確認した結果を記事にしています。

目次


変数

変数は let により定義することができ、通常はimmutable(不変)である。 mut を付けることにより、mutable(可変)とすることができる。

immutableである場合

下記のように、代入しようとすると、

fn main() {
    let x = 3;
    x = x + 1;
    println!("{}", x);
}

immutableであるため、エラーが発生する。

error[E0384]: cannot assign twice to immutable variable `x`
 --> demo.rs:3:2
  |
2 |     let x = 3;
  |         -
  |         |
  |         first assignment to `x`
  |         help: make this binding mutable: `mut x`
3 |     x = x + 1;
  |     ^^^^^^^^^ cannot assign twice to immutable variable

error: aborting due to previous error

mutableである場合

mutableであるため、下記のように代入した場合では、

fn main() {
    let mut x = 3;
    x = x + 1;
    println!("{}", x);
}

しっかりと返ってきてくれる。

4

変数を使っていなかった場合

a, b の2つの変数を用意して、a のみを出力した場合、

fn main() {
    let a = 3;
    let b = 4;
    println!("{}", a);
}

warningが出てくれて、無駄コードを減らせますね。便利だ。

warning: unused variable: `b`
 --> demo.rs:3:6
  |
3 |     let b = 4;
  |         ^ help: consider prefixing with an underscore: `_b`
  |
  = note: `#[warn(unused_variables)]` on by default

3

型(data type)

私はさっくり書く時は、PHPなど動的型付けで型を考えずにバシバシ書きますが、 静的型付けの方が、webAPIやバッチ処理などある程度厳密に処理しなければならないシステムの場合、 コードを追っかけるのが辛くなるので静的型付けの方が好きです。(小並感)

変数に対して型を付ける場合は、型定義をしてもしなくてもOKで、 する場合は、 : によって宣言します。

fn main() {
    let x = 2.0; // f64
    let y: f32 = 3.0; // f32
}

スカラー型(Scalar Type)

整数型(Integer Types)
  • 型一覧
Length Signed Unsigned
8-bit i8 u8
16-bit i16 u16
32-bit i32 u32
64-bit i64 u64
128-bit i128 u128
arch isize usize

archとはなんぞや・・・

Additionally, the isize and usize types depend on the kind of computer your program is running on: 64 bits if you’re on a 64-bit architecture and 32 bits if you’re on a 32-bit architecture.

原文によれば、実行環境のアーキテクチャによって、64bit/32bitが分けられるサイズとのこと。

  • 数値記法
Number literals Example
10進数(Decimal) 98_222
16進数(Hex) 0xff
8進数(Octal) 0o77
Binary 0b1111_0000
Byte (u8 only) b'A'

_ によってカンマ区切りを表現(visual separator)できるのはありがたい。 金額関連を扱う時に、 10000 とパット見た時に1000?10000?みたいな感じになるときが有る。 10_000 と書いてあった方が直感にわかりやすいから、使っていこうかな。

Integer Overflow

u8(0-255)の場合、+1するとオーバーフローが発生する。

fn main() {
    let mut x: u8 = 255;
    println!("{}", x);
    x = x + 1;
    println!("{}", x);
}

実行しても、overflowしとるでって出てきてくれる。

255
thread 'main' panicked at 'attempt to add with overflow', demo.rs:4:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

ドキュメントではChapter 9にてハンドリング方法が記載されているとのこと。

Rust uses the term panicking when a program exits with an error; we’ll discuss panics in more depth in the “Unrecoverable Errors with panic!” section in Chapter 9.

ただ、--release フラグつけてコンパイルをした場合は、整数オーバーフローになるとwrap around(u8 において256となった場合0となること)となる。

When you’re compiling in release mode with the --release flag, Rust does not include checks for integer overflow that cause panics. Instead, if overflow occurs, Rust performs two’s complement wrapping. In short, values greater than the maximum value the type can hold “wrap around” to the minimum of the values the type can hold.

浮動小数点数(Floating-Point Types)

f32 / f64 であり、デフォルトではモダンなCPUの速度に起因しないため f64 が使用されるが、厳密にするために f32 を使用しても良いみたい。

f32: https://doc.rust-lang.org/std/primitive.f32.html f64: https://doc.rust-lang.org/std/primitive.f64.html

Numeric Operations

加減乗除は全て対応している。

fn main() {
    // addition
    let sum = 5 + 10;

    // subtraction
    let difference = 95.5 - 4.3;

    // multiplication
    let product = 4 * 30;

    // division
    let quotient = 56.7 / 32.2;

    // remainder
    let remainder = 43 % 5;
}
論理型(The Boolean Type)

bool で指定する。

fn main() {
    let t = true;
    let f: bool = false;
}
文字型(The Character Type)

char で1文字単位で保持することができる。

fn main() {
    let c = 'z';
    let z = 'ℤ';
    let heart_eyed_cat = '😻';
}

その一文字とは、UnicodeでU+0000 - U+D7FF, U+E000 - U+10FFFFである。

Unicode Scalar Values range from U+0000 to U+D7FF and U+E000 to U+10FFFF inclusive.

混合型(Compound Types)
タプル(The Tuple Type)

() で囲って複数の変数を格納可能にする。

fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);
}
配列型(The Array Type)

多数の値をコレクションできる型(array型)

fn main() {
    let a = [1, 2, 3, 4, 5];
}

初期化設定は下記のように記載できる。

// let a = [3, 3, 3, 3, 3];
let a = [3; 5];

配列アクセスは配列番号指定で可能である。 ただし、配列数以上のアクセスに対しては、rumtime errorとなるため注意が必要です。

fn main() {
    let a = [1, 2, 3, 4, 5];

    let first = a[0];
    let second = a[1];
}