Rust 学習記
Rust について学習した過程の記録。コメント等ご自由にどうぞ。
Rust を初めて触ったのは5年前くらい?8年前?もはや覚えていない。実用的なプログラムを作る目的で使ったことはない。
Rust のユーザーフォーラムとしては https://users.rust-lang.org/ がある。何回か質問を投稿したことがあるが、みんな優しい。
ブール (Boolean)
ブール型は bool
と表し、値は true
と false
と表す。b
の否定は !b
、a
と b
の選言は a | b
、連言は a & b
、排他的選言は a ^ b
、等価は a == b
、非等値は a != b
、 順序は C などと同様に a > b
, a < b
, a >= b
, a <= b
と表す。
数 (number)
u8
は u16
, u32
, u64
, u128
も同様に2の冪指数を8から対応する数に変えたものを表す型。
i8
は i16
, i32
, i64
, i128
も同様に2の冪指数を
f32
と f64
はそれぞれ IEEE 754-2008 の “binary32” と “binary64” の 浮動点型。
usize
は実行される機械のポインター型と同じビット数の符号無し整数型。プロセスの任意のメモリーアドレスを表現できる。
isize
は実行される機械のポインター型と同じビット数の符号有り整数型。オブジェクトや配列の大きさの理論的な上限は isize
の最大値である。
usize
と isize
は少なくとも 16 bits はある。多くの Rust のコードは usize
と isize
が 32 bits か 64 bits であることを前提にしているので、16 bits だと動かないかもしれない。
文字と文字列 (textual)
char
は Unicode スカラー値を表すための型で、符号無し 32 bit 整数であり、範囲外の値が入ったものを作ったときの動作は未定義である。
str
は符号無し 8-bit 整数のスライスと同様に表現されるが、その値は有効な UTF-8 であると仮定され、範囲外では未定義と考えて良い。
'5'
で char
の値の表現、"hello"
で str
の値の表現になる。
r#""string""#
や r##"#1, #2, #4."##
のようにして、生文字列リテラルになる。生文字リテラルを表す片方の括弧に含まれる #
は 255 文字まで。
ボトム (never)
!
は never type と呼ばれる。(多分)空集合である。(多分)ボトム型である。(多分)値が帰ってこない関数の返却型を指定するときに使うやつ。
複型の固定長の組 (組, tuple)
Rust において組 (tuple) は複数の型の固定長の(数学的)組である。
組型 (tuple type) は異なる型のリストからなる構造的型で、文法は
⟨tuple type⟩ ::= ‘(’ × ‘)’ | ‘(’ × (⟨type⟩ × ‘,’)+ × ⟨type⟩? × ‘)’ ;
である。組値は組表現
⟨tuple expression⟩ ::= ‘(’ × ⟨tuple elements⟩? × ‘)’ ;
⟨tuple elements⟩ ::= (⟨expression⟩ × ‘,’)+ × ⟨expression⟩? ;
から生成される。
組と組構造体のフィールドには
⟨tuple indexing expression⟩ ::= ⟨expression⟩ × ‘.’ × ⟨tuple index⟩ ;
で到達できる。
⟨tuple index⟩ ::= ⟨integer literal⟩ ;
である。添字は 0 から数える。
単型の固定長の組 (配列, array)
単型の固定長の(数学的)組を Rust では配列 (array) と呼ぶ。
⟨array type⟩ ::= ‘[’ × ⟨type⟩ × ‘;’ × ⟨expression⟩ × ‘]’ ;
⟨expression⟩
は usize
として評価される定表現でなければならない。配列の表現は以下の定義で書き下す。
⟨array expression⟩ ::= ‘[’ × ⟨array elements⟩? × ‘]’ ;
⟨array elements⟩ ::= ⟨expression⟩ × (‘,’ × ⟨expression⟩)* × ‘,’? | ⟨expression⟩ × ‘;’ × ⟨expression⟩ ;
⟨array elements⟩
の前者の表現は要素を列挙して指定する意味になる。後者の表現の ;
の前の ⟨expression⟩
は repeat operand、後ろは length operand といい、[a; 3]
は [a, a, a]
という意味になる。
配列 (array) とスライス型の値に対して、添字を角括弧で囲んだものを後置することでその添字付けられた要素にアクセスできる。添字は 0 から数える。
⟨index expression⟩ ::= ⟨expression⟩ × ‘[’ × ⟨expression⟩ × ‘]’ ;
それ以外の型に対しては、a[b]
は *std::ops::Index:index(&a, b)
または *std::ops::IndexMut::index_mut(&mut a, b)
に等値である。
配列とスライス以外の型について、添字表現は Index トレイトと IndexMut トレイトを実装する事により実装できる。
スライス (slice)
Rust においてスライス (slice) は動的に大きさが決定される連続列へのビューであり、単型の可変長の組を表すのに使われる。型は
⟨slice type⟩ ::= ‘[’ × ⟨type⟩ × ‘]’ ;
と表す。以下の表現がよく現れる。(よく見るけれど意味はまだ私は分かってない。後でやる。)
-
&[T]
: ‘shared slice’ -
&mut [T]
: ‘mutable slice’ -
Box<[T]>
: ‘boxed slice’
構造体 (struct)
struct
型は多型の積であり、型のフィールドsと呼ばれる。
struct
のインスタンスは struct 表現から作られる。struct
のメモリーレイアウトはデフォルトでは未定義で、repr
属性で固定したりできる。struct
のフィールドは visibility modifier で修飾できる。
tuple struct 型は struct 型のフィールドが匿名である版である。
unit-like struct 型は struct 型のフィールドを持たない版である。
Rust の struct
型は C の struct
型、ML 族の record 型、Lisp 族の struct 型に相当する。
列挙体 (enumeration)
Rust において、列挙体 (enumeration または enum) は a nominal enumerated type かつ a set of constructors として定義される。
Rust において、列挙型 (enumerated type) は名前的 (nominal) で多型的 (heterogeneous) で素 (disjoint) な合併 (union) 型であり、enum
item により名前が表現される。
定義する文法は以下の通り。
⟨enumeration⟩ ::= ‘enum’ × ⟨identifier⟩ × ⟨generic params⟩? × ⟨where clause⟩? × ‘{’ × ⟨enum items⟩? × ‘}’ ;
⟨enum items⟩ ::= ⟨enum item⟩ × (‘,’ × ⟨enum item⟩)* × ‘,’? ;
⟨enum item⟩ ::= ⟨outer attribute⟩* × ⟨visibility⟩? × ⟨identifier⟩ × (⟨enum item tuple⟩ | ⟨enum item struct⟩)? × ⟨enum item discriminant⟩? ;
⟨enum item tuple⟩ ::= ‘(’ × ⟨tuple fields⟩? × ‘)’ ;
⟨enum item struct⟩ ::= ‘{’ × ⟨struct fields⟩? × ‘}’ ;
⟨enum item discriminant⟩ ::= ‘=’ × ⟨expression⟩ ;
例
enum Animal {
Dog,
Cat,
}
let mut a: Animal = Animal::Dog;
a = Animal::Cat;
enum
item は型と variants の数の双方によって宣言される。
列挙体は構造的に型によって表現できず、enum
item への名前付き参照として表現されなければならない。
enum
型は ML の data
コンストラクターや Limbo の pick ADT と同等である。