Rust book (2018 Edition) の学習用リポジトリ
- 変数は基本Immutable
- ImmutableとMutableのトレードオフ
- 大きなデータ構造の場合はインスタンスのコピーを生成するよりもインスタンスを変更した方が早い
- 小さなデータ構造の場合は新しいインスタンスを生成して、関数型な書き方で書いた方がわかりやすい
- Constantはどのスコープでも宣言可能
- Shadowingで同じ名前の変数を再宣言できる
- Shadowingで再宣言した変数は元の変数とは別の型として宣言可能
- Scalar Types
- Integer Types
8-bit
,16-bit
,32-bit
,64-bit
,128-bit
,arch
の長さでそれぞれsignedとunsignedがある- signedは
i
から、unsignedはu
から始まる- unsigned 32-bitの場合
u32
- unsigned 32-bitの場合
- signedの長さ�(nはbit数)
- -(2n-1) ~ 2n-1 - 1
- unsignedの長さ(nはbit数)
- 2n - 1
arch
(isize
とusize
) は実行環境に依存する- 3桁ずつ
_
で区切って表現可能 (10000
と10_000
は同じ) 0x
から始まるHex表記,0o
から始まるOctal表記,0b
から始まるBinary表記などが可能- デフォルトは
i32
基本的にはこれを使うのが速い
- Floating Point Type
f64
(64bit)とf32
(32bit)がある
- Character Types
- シングルクオートで囲まれる
- Unicode Scalar Valueなので、ASCII以外にも日本語などを表すこともできる
- Integer Types
- Compound Types
- The Tuple Type
- 最初に宣言した長さから変更できない
- タプルの各要素へは
x.0
のように{変数}.{index}
でアクセスできる
- The Array Type
- 他の多くの言語と違って、固定長
- 可変長な型でvectorというのがあるらしい
- 型を指定する場合は
[型名; 長さ]
を記述 - Arrayの長さより大きいindexで要素にアクセスするとruntime errorになる
- The Tuple Type
- Statements and Expressions
- Statementは値を返さない
- 故に
let x = (let y = 6);
のようにStatementを変数に入れることはできない - 他言語にあるような
x = y = 6
のような書き方もできない
- 故に
{}
で新しいスコープのブロックを作ることができる{}
ブロックの中は最終的に値を返すので、Expressionであり、Expressionに最後のセミコロンはいらない- 故にブロックの最後の行の処理はセミコロンが不要になる
let x = 5;
とlet x = { 5 };
は同じになる
- Statementは値を返さない
- Functions with Return Values
- 値を返す関数の処理ブロック内の最終行はExpressionなのでセミコロンは不要
// 下記の例のそれぞれの x + 1 は
// Expression なのでセミコロン不要
let y = {
let x = 5;
x + 1
}
fn plus_one(x: i32) -> i32 {
x + 1
}
if
Expressions- if文の条件式は
bool
でなければならない- 暗黙的に
bool
以外の型をbool
に変換しないので、明示的にbool
�で条件を書く必要がある
- 暗黙的に
if
は Expression なので、let
statement の右辺として使用できるif
Expression が返す値の型は統一されていないといけないif
で返す値とelse
で返す値が違うとエラー
- if文の条件式は
- Repetition with
loop
loop
は Expression なので、let
statement の右辺として使用できる
// numberがi32の場合、次のようなエラー�になる
error[E0308]: mismatched types
--> src/main.rs:10:8
|
10 | if number {
| ^^^^^^ expected bool, found integral variable
|
= note: expected type `bool`
found type `{integer}`
- Ownership Rules
- 3つのルール
- Rustの各値値には
owner
という変数をもつ - 一度に所有できる
owner
は1つだけ owner
がスコープから外れると、その値は削除される
- Rustの各値値には
- 3つのルール
- The
String
TypeString
は mutable にできるが、string literal
は immutable でしか扱えない- メモリの使い方が違うことによる違い
- Memory and Allocation
string literal
はハードコードされるので、コンパイル時に内容がわかる- 故に
string literal
は高速であるが、immutableしか扱えない String
型はmutableで扱うことができ、動的に内容を変えることができるが、それ故にコンパイル時に必要なメモリサイズが分からない- 変数がScopeから外れると、Rustは
drop
という特別な関数を自動で呼ぶ - integerの場合、値を代入した変数を別の変数に代入した時には値のコピーが代入される
- 値はそれぞれstackにpushされる
String
型の場合だと、コピーが代入されるわけではないString
は ポインタの位置, length, capacity のデータをstackに持つString
の値自体はheapに保存される- 代入時にコピーされるのはstackに持っているデータなので、値自体は同じポインタ位置から参照することになる
- 代入すると、代入元の変数は参照を失い(無効化され)、それ以降使用できなくなる
- 代わりに代入先の変数が参照を持つことになる -> 代入元変数が代入先変数に
move
した - これによって、スコープを抜ける時に複数変数から参照されているポインタを二重で解放する操作がなくなる
String
型でコピーを作成する場合はclone
メソッドを使用する- stackのデータだけでなく、heapのデータもコピーされる
- 場合によっては負荷が高い処理になることを頭に入れて使用すること
- Stack-Only Data
Integer
などはStackに値が溜まるのでclone
などは不要- 代入後も代入元の変数は無効化されず、使用できる
- これらを
Copy
特性と呼ぶ Copy
特性のある型- integer
- floating point
- bool
- char
- 要素が
Copy
特性のみで構成される tuple
- Ownership and Functions
- 関数の引数に値を渡すときも代入するときと同じように元の変数は無効化される
- ※
Copy
特性を持つものは無効化されない
- ※
- 関数の引数に渡した値を再度使いたい場合は、tuple型で元の値と関数で処理した結果を一緒に返すという方法もある
- 関数の引数に値を渡すときも代入するときと同じように元の変数は無効化される
- 関数の引数に渡す値を参照にすることで変数を無効化しない方法での実装ができる
&
をつけると参照を表す&mut
でmutableな参照を表す- mutableな参照はスコープ内で1度しか渡せない
- スコープ内でimmutableに参照している場合もmutableな参照はできない
- Dangling References
- Rustではコンパイラが宙ぶらりんのポインタを作らないことを保証する