エラーハンドリング
NagiScript のエラーハンドリング戦略を学びます。
Result /
Option
は組み込みの型としては存在しません。enum
で自作して使います。エラーを上位へ伝播させる
? 演算子は未実装なので、エラー回避は
if / else の分岐で行います。
Result を enum で自作する
まず
enum で成功・失敗の状態を定義します。値の生成は
Result.Ok のように括弧なしで生成します(データを持つバリアントのみ括弧が必要)。
enum Result {
Ok
NotFound
}
fn find(key: i32) -> Result {
if key == 1 {
return Result.Ok
}
return Result.NotFound
}
fn main() {
val r = find(2)
val st = match r {
Ok => "found",
NotFound => "missing",
}
println(st)
}
match のパターン
match のパターンには裸のバリアント名(Ok
/
NotFound)を使います。どのバリアントにも一致するワイルドカードは
_ です。
enum Result {
Ok
NotFound
}
fn find(key: i32) -> Result {
if key == 1 {
return Result.Ok
}
return Result.NotFound
}
fn main() {
val r = find(2)
match r {
Ok => println("found"),
_ => println("missing"),
}
}
エラー回避は if / else 分岐
? 演算子は未実装なので、エラーの判定・回避は
if / else と
明示的な return で行います。
fn divide(a: i32, b: i32) -> i32 {
if b == 0 {
println("zero division")
return 0 // エラー時は別の値で回避
}
return a / b
}
fn main() {
val x = divide(10, 2)
println(x)
}
enum DivResult {
Ok
Error
}
fn safe_divide(a: i32, b: i32) -> DivResult {
if b == 0 {
return DivResult.Error
}
return DivResult.Ok
}
fn main() {
val r = safe_divide(10, 0)
match r {
Ok => println("divide ok"),
Error => println("zero division"),
}
}
明示 return の規約
ブロック末尾の暗黙
return(式ブロック)は非対応です。戻り値のある関数は必ず
return を書き、戻り値を返さない関数は
-> を付けません。
fn read_config(name: string) -> string {
if name == "main" {
return "module:main"
}
return "not found"
}
fn main() {
println(read_config("main"))
}
panic
回復不能なエラーには組み込みの
panic を使います。引数は 1
個で、プログラムを停止します。
fn divide_or_panic(a: i32, b: i32) -> i32 {
if b == 0 {
panic("Division by zero")
}
return a / b
}
エラーハンドリングの流れ
enum で状態(Ok / NotFound / Error など)を定義
↓
関数の冒頭で if / else によりエラーを判定
↓
結果を return で明示的に返す
↓
match でバリアントを分岐
├─ Ok => 正常処理を続行
└─ NotFound => 別の処理
↓
? 演算子は未実装。伝播したい場合は if / else で分岐させる
