実行フローを制御するif
について説明します。
最も単純なif分岐の構文は、if (条件式) { 条件式がtrueの時の処理 }
です。条件式
の部分にはブール値、オプション型、エラー共用体、のいずれかが記述できます。{}
で囲われた部分をブロックと呼びます。
条件式にブール値を使用するコードは次の通りです。条件式がtrue
の場合のみ、ブロックが実行されます。
examples/ch04-basic-syntax/src/if.zen:4:10
test "the simplest if" {
var x: u32 = 1;
if (x == 1) {
// `x == 1`の場合のみ実行される
ok(true);
}
}
さらに、if
の条件式がfalse
の場合、else if (条件式) { ... }
で次の候補の条件を指定することが可能です。全ての条件式がfalse
の場合に、その他全ての場合の処理をelse { ... }
で記述することもできます。
examples/ch04-basic-syntax/src/if.zen:12:24
test "else if" {
var x: u32 = 2;
if (x == 1) {
// `x == 1`の場合のみ実行される
ok(false);
} else if (x == 2) {
// `x == 2`の場合のみ実行される
ok(true);
} else {
// `x == 1`でも`x == 2`でもない場合のみ実行される
ok(false);
}
}
ブロック内の文が1文だけの場合、中括弧 ({}
) を省略することが可能です。コーディングスタイルとしては、このような場合も中括弧を書くことをお勧めします。
examples/ch04-basic-syntax/src/if.zen:26:29
test "if without {}" {
if (true)
ok(true);
}
条件式にオプション型の値を使用することができます。この場合、オプション型の値がnull
でなければ、if
のブロックが実行されます。オプション型の値を条件式に使用する場合、アンラップした値をキャプチャしなければなりません。そのため、基本構文はif (オプション型の値) |アンラップした値| { ... }
となります。
examples/ch04-basic-syntax/src/if.zen:31:43
test "if optional" {
var x: ?u32 = 42;
if (x) |value| {
// このブロックは実行される
ok(value == 42);
}
var y: ?u32 = null;
if (y) |value| {
// このブロックは実行されない
ok(false);
}
}
条件式がオプション型の値の場合、else
で値がnull
の場合の処理を記述することができます。
examples/ch04-basic-syntax/src/if.zen:45:53
test "else optional" {
var x: ?u32 = null;
if (x) |value| {
ok(false);
} else {
// `value` == `null`の場合
ok(true);
}
}
アンラップした値は、if
ブロック内でのみ使用できます。
examples/ch04-basic-syntax/src/if.zen:55:67
test "scope of unwrapped value" {
var x: ?u32 = 42;
if (x) |value| {
// `value`はこのブロック内でのみ有効
ok(value == 42);
} else {
// Compile error
// ok(value == 42);
}
// Compile error
// ok(value == 42);
}
条件式にエラー共用体の値を使用することができます。この場合、エラー共用体の値がエラー型でなければ、if
のブロックが実行されます。エラー共用体の値を条件式に使用する場合、アンラップした値をキャプチャしなければなりません。加えて、エラー型の値をキャプチャして処理するelse
を記述する必要があります。そのため、基本構文はif (エラー共用体の値) |アンラップした値| { ... } else |エラー型の値| |err| { ... }
となります。
examples/ch04-basic-syntax/src/if.zen:69:80
test "if error union" {
var x: anyerror!u32 = 42;
if (x) |value| {
// `x`がエラーでない場合の処理
// アンラップした値を`value`としてキャプチャ
ok(value == 42);
} else |err| {
// `x`がエラーの場合の処理
// エラー型の値を`err`としてキャプチャ
ok(false);
}
}
if (条件式) 代入式
のように、ブロックの代わりに代入式をif
の本体に書くことができます。
examples/ch04-basic-syntax/src/if_expression.zen:41:46
test "if assign expression" {
var x: u32 = 42;
if (x == 42) x += 1;
ok(x == 43);
}
Zenではif
は式です。すなわち、値を返すことが可能です。次のコードは、実用上意味を持ちませんが、if
が式であることを表しています。
examples/ch04-basic-syntax/src/if_expression.zen:4:8
test "concept of if expression" {
// `x`に`if`の結果を代入する
var x = if (true) {};
ok(@TypeOf(x) == void);
}
if (true) { }
の値をx
に代入しています。ブロック{ ... }
が返す値は何もないことを表すvoid
型の値です。
もう少し有用な例を見てみましょう。
examples/ch04-basic-syntax/src/if_expression.zen:10:15
test "if expression" {
var x: u32 = 41;
var y = if (x == 42) @to(u32, 1) else @to(u32, 0);
ok(y == 0);
}
上のコードでは、x
の値が42
であればy
に1
が、それ以外であればy
に0
が代入されます。
if
式の値を利用する場合、if
ブロックの値とelse if / else
ブロックの値とが、全て同じ型でなければなりません。特に、else
を省略した場合に、void
型の値を返すelse {}
があるかのように振る舞います。
test "if expression without else" {
var x: u32 = 42;
var y: u32 = if (x == 42) @to(u32, 1);
}
上のコードは、次のコンパイルエラーになります。
error[E02047]: unable to convert 'void' to 'u32'
var y: u32 = if (x == 42) @to(u32, 1);
~
このエラーは、if
ブロックがu32
を返しているにも関わらず、else
ブロックがvoid
を返していることを意味しています。u32
の値を返すelse
ブロックを書くと、このエラーは解消できます。
{}
を使ったブロックで複数行の処理を書き、その結果をif
の値にすることもできます。そのような場合には、ラベル付きブロックを使います。
通常ブロック ({}
) の値はvoid
になりますが、ラベルを付けて、値をbreak
することで、その値を返すことができます。
examples/ch04-basic-syntax/src/if_expression.zen:17:29
test "concept of labeled block" {
// `result: {}`はラベル付きブロック
var x: u32 = result: {
// 複数行の文を記述する
const y = 40;
const z = 2;
// ラベルを指定して式を`break`する
break :result (y + z);
};
// `break`された式の値が格納されている
ok(x == 42);
}
ラベル付きブロックを利用することで、複雑な計算が必要な値をif
式の値として返すことができます。
examples/ch04-basic-syntax/src/if_expression.zen:31:39
test "labeled if" {
var x: u32 = 42;
var y = if (x == 42) if_block: {
var z = x * 2;
break :if_block z;
} else @to(u32, 0);
ok(y == 84);
}
☰ 人の生きた証は永遠に残るよう ☰
Copyright © 2018-2020 connectFree Corporation. All rights reserved. | 特定商取引法に基づく表示
Zen, the Zen three-circles logo and The Zen Programming Language are trademarks of connectFree corporation in Japan and other countries.