The Book の 3 章『Common Programming Concepts』を進めていく。
https://doc.rust-lang.org/book/ch03-00-common-programming-concepts.html
Rust における変数はデフォルトで immutable となっており mut を付けることで mutable な変数となる。
fn main() {
let x = 5;
println!("The value of x is: {x}");
x = 6;
println!("The value of x is: {x}");
}
上記のように immutable な変数 x に再代入しようとすると、
error[E0384]: cannot assign twice to immutable variable `x`
--> src\main.rs:4:5
|
2 | let x = 5;
| -
| |
| first assignment to `x`
| help: consider making this binding mutable: `mut x`
3 | println!("The value of x is: {x}");
4 | x = 6;
| ^^^^^ cannot assign twice to immutable variable
cannot assign twice to immutable variable というエラーが表示される。
const STANDARD_GRAVITY: f32 = 9.80665;
println!("Standard gravity is {STANDARD_GRAVITY} m/s^2");
定数は const keyword で定義され、その値の型を注釈する必要がある。
定数はグローバルスコープを含めてどのスコープでも定義することができ、定義されたスコープ内で有効となる。
変数とは異なり mut を使うことはできず、常に immutable となる。
fn main() {
let x = 5;
let x = x + 1;
println!("The value of x is: {x}");
{
let x = x * 2;
println!("The value of x in the inner scope is: {x}");
}
let x = x + 2;
println!("The value of x is: {x}");
}
上記コードを実行すると、次のような出力となる。
The value of x is: 6
The value of x in the inner scope is: 12
The value of x is: 8
let keyword で同じ変数名を指定して再宣言することができる。
最初の let x = 5 に対して let x = x + 1 とすることで、この時点で x: 6 となっている。
直後のブロックスコープ内では直前の x の値が 6 なので、let x = x + 2 で x: 12 となる。
ブロックスコープを抜けるとシャドーイングが終了するので x の値は 6 となり、
その後の let x = x + 2 では x: 8 となる。
Rust は静的型付け言語のため、コンパイルの時点ですべての型が決まっている必要がある。
let guess = "614".parse().expect("Not a number!");
上記のコードを実行すると、以下のようなエラーが表示される。
$ cargo run
Compiling variables v0.1.0 (/home/oshiroman/projects/learning_rust/chapter3)
error[E0284]: type annotations needed
--> src/main.rs:2:9
|
2 | let guess = "614".parse().expect("Not a number!");
| ^^^^^ ----- type must be known at this point
|
= note: cannot satisfy `<_ as FromStr>::Err == _`
help: consider giving `guess` an explicit type
|
2 | let guess: /* Type */ = "614".parse().expect("Not a number!");
| ++++++++++++
For more information about this error, try `rustc --explain E0284`.
error: could not compile `variables` (bin "variables") due to 1 previous error
parse メソッドで文字列 → 数値へ変換する場合、型注釈またはターボフィッシュ parse::<T>() を指定する。
// 型注釈
let guess: u32 = "614".parse().expect("Not a number!");
// ターボフィッシュ
let guess = "614".parse::<u32>().unwrap();
【参考記事】Rustで文字列を数値に変換(parse, from_str_radix)
スカラー型は単独の値を表し、整数、浮動小数点数、論理値、文字の 4 つの型がある。
整数型 - Integer Types
符号付き 32-bit 整数は i32 、符号なし 64-bit 整数は u64 のように表せる。
isize と usize は動作する環境に依存し、64-bit アーキテクチャであれば 64-bit 整数として振る舞う。
整数型の基準型は i32 となっている。
浮動小数点型 - Floating-Point Types
Rust の浮動小数点数は IEEE-754 に従っており f32 は単精度、 f64 は倍精度。
浮動小数点数の基準型は f64 となっている。
let x = 3.0; // f64
let y: f32 = 2.7182818;
数値演算
// addition
let sum = 2 + 3;
println!("[sum] {sum}");
// subtraction
let diff = 1.732 - 2.236;
println!("[diff] {diff}");
// multiplication
let product = 12345679 * 23;
println!("[product] {product}");
// division
let quotient = 58.0 / 173.1;
let truncated = -2401 / 2443;
println!("[quotient] {quotient}");
println!("[truncated] {truncated}");
// remainder
let remainder = 341 % 17;
println!("[remainder] {remainder}");
[sum] 5
[diff] -0.5040000000000002
[product] 283950617
[quotient] 0.3350664355863663
[truncated] 0
[remainder] 1
論理値型 - The Boolean Type
bool 型と表され true と false の二値。
// boolean
let t = true;
let f: bool = false;
文字型 - The Character Type
char 型と表され、シングルクォートで文字を囲う。
// character
let c = 'c';
let r = 'ℝ';
let zzz = '💤';
タプル型 - The Tuple Type
タプルは複数の型を一つの複合型にまとめる。
// tuple
let tuple: (i32, f64, i8) = (2119, 9.8, -3);
let (a, b, c) = tuple;
println!("a: {a}, b: {b}, c: {c}"); // a: 2119, b: 9.8, c: -3
アクセスしたい値の番号を . で繋げて記述することで、タプルの要素にアクセスすることができる。
let tup = ("PERFECT", 100, false);
let perfect = tup.0;
let one_hundred = tup.1;
let f = tup.2;
println!("[perfect] {perfect} [one_hundred] {one_hundred} [f] {f}");
// [perfect] PERFECT [one_hundred] 100 [f] false
配列型 - The Array Type
配列はタプルと異なり、含まれる値はすべて同じ型でなければならない。
配列は固定長であるため、宣言後はそのサイズを変更することはできない。
可変長なコレクションを使用したい場合はベクタを使用する。
// array
let directions = ["North", "East", "South", "West"];
let east = directions[1];
println!("[1] {east}"); // [1] East
宣言時に要素の型と長さを指定したり、初期化する値を指定することもできる。
let all_u64: [u64; 10] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
let all_zero = [0; 10]; // let all_zero = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] と同義
println!("{all_u64:?}"); // [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
println!("{all_zero:?}"); // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]