📌 基本データ型
Rust の標準にある基本的なデータ型は次のとおりです:
- 整数型:
i8
,u8
,i16
,u16
,i32
,u32
,i64
,u64
,isize
,usize
- 浮動小数点型:
f32
,f64
- ブーリアン型:
bool
- 文字列型:
char
- タプル(複合)型:
(500, 6.4, true)
,()
はユニット. - 配列型:
[1,2,3,4,5]
,[3;5] = [3,3,3,3,3]
数値型のリテラルには次のものが使えます:
-
98_222
(10進数) -
0xff
(16進数) -
0o77
(8進数) -
0b1111_0000
(2進数) -
b'A'
(バイト) -
0.
(浮動小数点数)
基本的なデータ型はコピートレイトを実装しています.また,複合・配列型については,含まれている要素がすべてコピートレイトを実装していれば,全体もコピートレイトを実装したことになります.参照も型の1つで,不変参照はコピートレイトを実装していますし,可変参照は実装していません.参照の参照ということも可能です.
fn main() {
let a = 42;
let ref_ref_ref_a = &&&a;
let ref_a = **ref_ref_ref_a;
let b = *ref_a;
print!("{} {}", a, b);
}
比較するときは基本的に同じ型でなくてはならないので,参照もまた型であるということが以下でわかります.
fn main() {
let a = 10; // immutable object
let a_ref = &a; // reference
let a_ref_ref = &a_ref; // reference to reference
println!("{}", a == a_ref);
// error[E0277]: can't compare `{integer}` with `&{integer}`
println!("{}", a_ref_ref == a_ref);
// error[E0277]: can't compare `&{integer}` with `{integer}`
}
Rust は強い型推論を持っていますが,意図的にデータ型を指定したい場合があります.その場合は変数名の後ろに :
を付けてデータ型を指定します.
fn main() {
let a: i32 = 10;
let b: u32 = 20;
let c: f32 = 0.;
let d: &i32 = &50;
print!("{} {} {} {}", a, b, c, d);
}
変数は パターン を使って,要素を分解して束縛できます.
fn main() {
let (x,y,z) = (1,2,3);
let [a,b,c] = [4,5,6];
let (i,_,_) = (7,8,9);
println!("xyz= {} {} {}", x, y, z);
println!("abc= {} {} {}", a, b, c);
println!(" i= {}", i);
}
_
は ワイルドカード と呼ばれるもので,オブジェクトを無視するときに使います.Rust では同じスコープ内で,変数名を使い回すことができます.
fn main() {
let str_len = String::from("hello world!");
let str_len = str_len.len();
println!("{}", str_len);
}
あるスコープのさらにローカルなスコープにおいても外側にある変数名と同じ名前で新しく束縛できます.このとき,外側の変数はローカルから隠れます.これを シャドーイング と言います.
fn main() {
let a = 10;
{ // local scope
let mut a = 20;
a += 30;
println!("{}", a); // 50
}
println!("{}", a); // 10
}
明示的に数値オブジェクトを型変換して使いたい場合があります.その場合は as
を使います.
fn main() {
let a = 13u8;
let b = 7u32;
let c = a as u32 + b;
println!("{}", c);
let t = true;
println!("{}", t as u8);
}
📌 スライス
スライス は参照の1つで,別のオブジェクト内の連続した要素を指し示すものです.スライスを取得するには,オブジェクトに対して数列指定([m..n]
)します.参照なので,スライスの型は例えば配列だと &[T]
になります. T
は任意の型です.
fn main() {
let a = [1,2,3,4,5];
let a_slice = &a[1..3];
dbg!(a_slice); // [2,3]
}
🔹 数列
数列は Range
型と呼ばれるもので m..n
の形で指定します. m
と n
はそれぞれ開始値と終了値で, m
から n-1
までの連番を表します. m..=n
とすることで, m
から n
までの連番を表します.数列は for
式で利用できます.
fn main() {
let mut sum=0;
for i in 1..100 {
sum += i;
}
println!("sum={}", sum);
}
Rust はインデックスが 0
から始まります.数列指定では開始インデックスと終了インデックスを ..
を使って指定します.例えば m..n
なら [m, m+1, m+2, …, n-1]
となります. m..=n
の場合は [m, m+1, m+2, …, n]
となります.開始インデックスと終了インデックスは省略できます.
let s = String::from("hello");
let slice = &s[0..2];
let slice = &s[0..=2];
let slice = &s[..2];
let slice = &s[3..s.len()];
let slice = &s[3..];
let slice = &s[..];
🔹 文字列リテラル
文字列のスライスの型は &str
です.そして,文字列リテラルは不変の文字列スライス (&str
) です.
let s = "Hello, world!";