https://doc.rust-lang.org/book/second-edition/
3.1
let で変数定義 immutable let mut で mutable const で定数定義。実行時に計算するような値は入れられない。コードのあちこちで使うような値を入れる
let x = 5;
let x = x + 1;
↑ シャドーイング。仮に let x = 5; x = x + 1; と書いたらイミュータブルだから怒られる
3.2
i8, i16, i32, i64 で signed な数 u8 - 64 で unsigned isize, usize はアーキテクチャ任せ tuple は let x: (i32, f64, u8) = (50, 3.2, 8); みたいに定義 x.0, x.1, x.2 でアクセス let (a, b, c) = x; でスプレッド 配列は let a = [1,2,3];
4.1
let x = String from;
let y = x;
println!;
このコードはエラーになる。 shallow とか deep とかとも違い move といって、所有権が移動する 単純に let y = x.clone(); とすればうごく
let x = 1;
let y = x;
println!;
このコードは動く。 Copy trait を持ってる型なら勝手にコピーしてくれる。 「なんとなく shallow copy とか deep copy にはならなそうだな」と思ったらでいけそう
まぁまぁ普通にかける感じはするけど、流石に「一度渡したら以降使えない」だけだとつらいので、 4.2 の参照がある
4.2
let s1 = String from
len = calc
println! // コンパイルエラー
こうしちゃうと println でエラー。 所有権が calc にうつっちゃうのでもとのところでは使えない。 rust では & つけて参照渡しをすると、所有権は渡さずに値を借りる (borrowing) ことができて、 function を抜けたときに自動で返す挙動になる。
ただし、借りてきた値が immutable だと、破壊的な操作は実行できない mutable な操作をしたいならこう。
ちゃんと最初の定義から let mut でやって、 mutable な reference で書いていく
mutable reference には大きな制約があり、同じスコープ内に別の mutable/immutable reference を持つことができない。
let mut s = String from;
let r1 = &mut s;
let r2 = &mut s; // コンパイルエラーになる
let mut s = String from;
let r1 = &s;
let r2 = &s; // 問題なし
let r3 = &mut s; // コンパイルエラーになる
なぜ: r1 で読んで r2 で書いてをマルチスレッドでやったら data race 起きるじゃん 中括弧でスコープ分けてやればエラーにならない
rust は Dangling References (宙ぶらりんな参照) は作れないようになっている
s は dangle を抜けたらメモリ上から開放されるので、 &s は dangling reference になってしまう。が、 rust はこれがコンパイルエラーになる。 この例だと参照渡しせずに直接渡すのが正解。所有権が移動するので、 s が開放されずにすむ
まぁでも rust の旨味として、 mutable はあんまり使わないほうがいいんだろうなと思う
4.3
文字列の一部を切り出すのに slice 使う例が書かれてるんだけど、これ 2 バイト文字とかどうなるのって思ったら案の定使えないらしい。 いろいろ調べてたら下記の記事が参考になりそうだった。ともかく文字列操作は一筋縄ではいかないもよう
https://qiita.com/aflc/items/f2be832f9612064b12c6
ここでは immutable 保ったまま配列の一部を切り出すには slice つかうといいよくらいでよさそう
5
構造体
5.1
普通な感じ
こんなふうに作る ↓
let user1 = User ;
mutable にすれば再代入もできる ↓
特定のフィールドだけを mutable にしたりはできない。
これやるよりはあとから出てくる ..
使って新しいインスタンス作ったほうがよさそう。
let mut user1 = User ;
user1.email = String from;
構造体を作る関数 ↓ ES6 みたいに同じフィールドに同じ変数名で値をセットするときは省略できる
struct update syntax というので、別のインスタンスのフィールドを使って新しいインスタンスをつくれる。これまた ES6 っぽい。挙動も一緒で、下記だと email, username 以外は user1 の値が使われる
let user2 = User ;
tuple も名前をつけられる (Tuple structs) ↓
;
;
let black = Color;
let origin = Point;
5.2 An Example Program Using Struct
ここは一通り読んで書いてみたほうが良さそう。 構造体の具体的な使い方と、アノテーションとかが出てくる
5.3 Method Syntax
構造体へのメソッド追加
&self を書かなければ static メソッド(static という言い方はしてないので、誤解あるかも)
impl は分けてかける
6.1 Defining an Enum
定義は普通
引数にとったり呼び出しも普通
let four = V4;
let six = V6;
それぞれに違う struct にすることが可能
インスタンスメソッドをもたせたりもできる
.call;
m
The Option Enum and Its Advantages Over Null Values
他の言語でもよくある Optional だけど、 rust の場合は下記のような enum で実装されてる。
先の enum の例を踏まえると下記のようにかける
let some_number = Some;
let absent_number: = None;
なるほど
6.2 The match Control Flow Operator
パターンマッチはこんな感じ。単に値を返すだけじゃなくて処理を書いたり、値を扱ったり
Option を match であつかうとこんな感じ ↓
すべてのパターンを網羅してないとコンパイルエラーになる。 例えば上記の None => None を削るとエラー。
ほか全て、は _ placeholder で受けることができる。 ()
は何もしない
match some_u8_value
6.3 Concise Control Flow with if let
1 こだけマッチさせたいパターンだと match では冗長なときもあるので、そのときは if let も使う。 下記の例は else if も使っていて、これなら match を使ったほうが良いだろう
おそらく Option で使うことが多そう。
7.1 mod and the Filesystem
下記のように新しいプロジェクトを作ってからスタート。 lib についての詳しい説明はまたそのうち出てくるはず。
ざっくりいうとディレクトリ構成の通りにモジュールのネームスペースが切られるよって話がメイン
└── src
├── client.rs
├── lib.rs
└── network
├── mod.rs
└── server.rs
// client.rs
// network/mod.rs
// network/server.s
こういう構成のディレクトリにすると、
// lib.rs
と、こんな具合に呼び出せる。これは実質下記と一緒
7.2 Controlling Visibility with pub
上記のコードを呼び出してみる
// src/main.rs
extern crate communicator;
extern crate
でクレートを呼び出す。
これは main.rs か lib.rs にしか書くことができない。
main.rs, lib.rs は root モジュールと呼ぶ。
この main.rs ファイルを作った時点で、 communicator パッケージは binary crate と library crate の 2 つのクレートを持つことになる。 これは実行可能なプロジェクトでは一般的な構成で、うまく関心を分離(separation of concerns)できる。
これを書いただけだと下記のようなエラーになる。
error[E0603]: module `client` is private
--> src/main.rs:4:5
|
4 | communicator::client::connect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
要は client モジュールは private だから外部クレートから呼べないよというエラー。 rust はデフォルト private で、 pub をつけると public になる。
// lib.rs
// client.rs
このようにモジュールと関数どちらにも pub をつけられる。