構造体と列挙型
独自の型を定義する方法を学びます。
構造体 (Struct)
定義
struct Point {
x: f64
y: f64
}
struct Person {
name: string
age: i32
email: string
}
インスタンス化
val p = Point { x: 10.0, y: 20.0 }
val person = Person { name: "Alice", age: 30, email: "alice@example.com" }
フィールドアクセス
val x = p.x
val name = person.name
// フィールドの変更(var のみ)
var p2 = Point { x: 1.0, y: 2.0 }
p2.x = 10.0 // OK: p2 は var
メソッド
impl ブロックで定義する
メソッドは impl 型名 { ... } ブロック内に
fn として定義し、第一引数に
self: 型名 の注釈を必須とします。戻り値は
-> 構文と明示的な
return
で返します。整数・浮動小数の文字列化(str(x))や文字列
+ 連結は現行では使えないため、math
モジュールに依存する例は避けてください。
struct Point {
x: f64
y: f64
}
impl Point {
fn describe(self: Point) -> string {
return "point"
}
}
fn main() {
val p = Point { x: 3.0, y: 4.0 }
println(p.describe()) // point
}
列挙型 (Enum)
基本的な列挙型
enum の定義は裸のバリアント名 Red /
Green を列挙します。バリアント値を生成するときは
Color.Red のように括弧なしで生成できます(データを持つバリアントのみ括弧が必要、例: Some(42))。
enum Color {
Red
Green
Blue
}
val c = Color.Red
データを持つ列挙型
enum Shape {
Circle(f64) // radius
Rect(f64, f64) // width, height
}
fn kind(s: Shape) -> string {
val label = match s {
Circle(r) => "circle",
Rect(w, h) => "rect",
}
return label
}
fn main() {
val c = Shape.Circle(5.0)
val r = Shape.Rect(2.0, 3.0)
println(kind(c)) // circle
println(kind(r)) // rect
}
match のパターンは裸のバリアント名(Circle(r)
など)と _ を使います。データ生成は
Shape.Circle(5.0) のように
() 付きです。math.PI /
math.sqrt
のようなモジュールは現行では存在しないため、上記はモジュールに依存しない例にしています。
Result 相当の enum(自作)
エラーハンドリングのための Result 型は現行では組み込みとして存在しません。enum で自作します。
enum MathResult {
Value(f64)
DivByZero
}
fn divide(a: f64, b: f64) -> MathResult {
if b == 0.0 {
return MathResult.DivByZero()
}
return MathResult.Value(a / b)
}
fn main() {
val result = divide(10.0, 3.0)
val st = match result {
Value(v) => "ok",
DivByZero => "error",
}
println(st)
}
? 演算子
エラーを上位関数に伝播させる
? 演算子は未実装です。引数に結果を返す
enum を渡し、match
で分岐する形で実装します。ジェネリクス(Result<T, E>
のような
Vec2<T>)は現行では未実装/未検証なため、上記は単一の型を使って自作した例です。
ジェネリクス(ロードマップ)
Vec2<T> のようなジェネリクス構造体や
fn first<T>(...) -> T
のようなジェネリック関数は未実装/未検証です。struct Vec2 { x: f32, y: f32 }
のように具体的な型で定義してください。型パラメータは
List<i32>
など一部で限定的にしか使えず、List<T>
自体も LLVM
コード生成でリンクに失敗する既知バグがあるため、当面は構造体
+ 値渡しを推奨します。
Option 相当の enum(自作)
Option 型も組み込みでは存在しないため enum
で自作します。データを持つバリアント(Found(User))はパターン
Found(u) で取り出せます。find_user は失敗時に
Lookup.NotFound(括弧なし)で戻します。
struct User {
name: string
}
enum Lookup {
Found(User)
NotFound
}
fn find_user(id: i32) -> Lookup {
if id == 1 {
return Lookup.Found(User { name: "Alice" })
}
return Lookup.NotFound
}
fn main() {
val user = find_user(1)
match user {
Found(u) => println(u.name),
NotFound => println("not found"),
}
}
