RUST言語 入門日記 (1)

RUST言語を再度入門する時間があったので、大事なところをメモする。

イディオム

1. 関数のパラメータは極力所有権のない参照型にする。

&Stringではなく&str
&Vecではなく&[T]
&Boxではなく&T

暗黙的な参照外しがあるため、この方が汎用性が高くなる。

2. 文字列結合する時は極力format!を使う。

動的に変わる文字列の場合はpush_strにするしかない。

3. Rustはコンストラクターがないため、関連函数newよりオブジェクトを作る。

Default traitを実装すると、***_or_defaultが使えるようになる。例えば、
Option::unwrap_or_default()

4. コレクションはスマートポインター。

Deref traitを実装し、コレクションからスライスへ変換する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use std::ops::Deref;

struct Vec<T> {
data: RawVec<T>,
//..
}

impl<T> Deref for Vec<T> {
type Target = [T];

fn deref(&self) -> &[T] {
//..
}
}

5. Drop traitの実装は、関数がエラー終了や、panicじも実行される。

しかし、dropの中にpanic発した場合、スタックの後続dropは実行されないため、dropの実装はpanicが発生しないよう慎重に実装すべきである。

6. mem::{take(), replace()}を使って、所有権を残し、cloneを省く。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use std::mem;

enum MyEnum {
A { name: String, x: u8 },
B { name: String }
}

fn a_to_b(e: &mut MyEnum) {
if let MyEnum::A { name, x: 0 } = e {
// this takes out our `name` and put in an empty String instead
// (note that empty strings don't allocate).
// Then, construct the new enum variant (which will
// be assigned to `*e`).
*e = MyEnum::B { name: mem::take(name) }
}
}

Default traitが実装されてない場合、mem::replaceを使う。

7. トレーイト等価実装。

トレーイト 関数1 関数2
std::fmt::Display ***.to_string()
std::str::FromStr ***.parse()
std::convert::From ***::from() ***.into()
std::convert::TryFrom ***::try_from() ***.try_into()

8. for in と Iterator

into_iter
iter
iter_mut
がある。
for x in vec の場合 ディフォルトinto_iterが呼ばれる。
into_iterの場合、所有権がmoveされるため、元のvecが使えなくなる。
iterの場合参照を取る。

1
2
3
4
5
6
7
8
9
10
fn main() {
let names = vec!["Bob", "Frank", "Ferris"];

for name in names.into_iter() {
match name {
"Ferris" => println!("There is a rustacean among us!"),
_ => println!("Hello {}", name),
}
}
}

8. matchについて

1
2
3
match color {
Color::RGB(r, g, b) => println!("Red: {}, green: {}, and blue: {}!", r, g, b),
_ => println!("It doesn't matter what they are"),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

fn some_number() -> Option<u32> {
Some(42)
}

fn main() {
// 参照など
let reference = &4;
match reference {
&val => println!("Got a value via destructuring: {:?}", val),
}

match *reference {
val => println!("Got a value via dereferencing: {:?}", val),
}

let _not_a_reference = 3;
let ref _is_a_reference = 3;

let value = 5;
let mut mut_value = 6;

match value {
ref r => println!("Got a reference to a value: {:?}", *r),
}

match mut_value {
ref mut m => {
*m += 10;
println!("We added 10. `mut_value`: {:?}", m);
},
}

// 条件付き
let pair = (2, -2);
match pair {
(x, y) if x == y => println!("These are twins"),
(x, y) if x + y == 0 => println!("Antimatter, kaboom!"),
(x, _) if x % 2 == 1 => println!("The first one is odd"),
_ => println!("No correlation..."),
}

match some_number() {
Some(n @ 42) => println!("The Answer: {}!", n),
Some(n) => println!("Not interesting... {}", n),
_ => (),
}

}

9. Copyについて。

Clone は Copy の super trait。
Copy実装には Cloneの実装が必須。

CopyとDropは同時不可。

1
2
3
pub trait Copy: Clone {
// Empty.
}