08. 一般分岐構文 編
今回は LuneScript の一般分岐構文について説明します。
構文一覧
LuneScript は、次の一般分岐構文をサポートします。
- if
- switch
ちなみに、ここであえて「一般」分岐制御としているのは、 nilable 制御で別途分岐制御があるためです。
if
if 文は、次のように使用します。
// @lnsFront: ok
let val = 1;
if val == 1 {
print( "hoge" );
}
elseif val == 2 {
print( "foo" );
}
else {
print( "bar" );
}
説明は不要かと思いますが、次のように処理されます。
- if の式が成立している場合、 if のブロックが実行される。
- if の式が不成立で elseif の式が成立している場合、elseif のブロックが実行される。
- 全ての式が不成立の場合、else のブロックが実行される。
- elseif は複数存在しても良い。
- elseif, else は存在しなくてもよい。
- 式が 「不成立」 する条件は、その式の結果が nil か false の時。
bool 値との比較
LuneScript では、 bool 値との比較を推奨していません。
具体的には次のようなオペレーションを推奨しません。
// @lnsFront: ok
let val1 = true;
if val1 == true {
}
if val1 == false {
}
if val1 ~= false {
}
if val1 ~= true {
}
上記のオペレーションは、近い将来廃止予定です。
現在は、コンパイル時に warning メッセージを出力します。
bool の真偽値によって処理を切り替える場合、 次のようにしてください。
// @lnsFront: ok
let exp = true;
if exp {
print( "exp is true" );
}
else {
print( "exp is false" );
}
if not exp {
print( "exp is false" );
}
switch
switch 文は次のように使用します。
// @lnsFront: ok
let val = 1;
switch val {
case 1 {
print( "hoge" );
}
case 2 {
print( "foo" );
}
default {
print( "bar" );
}
}
なおこのサンプルは、上記 if のサンプルと同義です。
switch の case には、次のように複数の式を書けます。
// @lnsFront: ok
let val = 1;
switch val {
case 10, 20, 30 {
print( "hoge" );
}
default {
print( "bar" );
}
}
これは次の if 文と同義で、いづれかの値に一致すると、そのブロックを実行します。
// @lnsFront: ok
let val = 1;
if val == 10 or val == 20 or val == 30 {
print( "hoge" );
}
else {
print( "bar" );
}
switch 文で注意すべき点は、 C 言語などと違い break が不要であることです。
例えば次の break は、 switch 文を抜けるのではなく for 文を抜けることになります。
// @lnsFront: ok
for count = 1, 10 {
switch count {
case 5 {
break;
}
}
}
enum 値のフロー解析
switch 条件が enum 値の場合、 case 文で全ての enum 値が指定されているかどうかをチェックしてフロー解析します。
例えば次の場合、
func()
関数内の switch 文の後にある print()
文は到達不可のエラーとなります。
これは、 enum 値 Val の全ての値( Val1, Val2 ) のケースに
return が指定されているためです。
// @lnsFront: error
enum Val {
Val1,
Val2,
}
fn func( val:Val ) {
switch val {
case .Val1 {
return;
}
case .Val2 {
return;
}
}
print( work ); // error : 全ての enum 値の case があり、 return している
}
また、全ての enum 値に対する case が指定されていて、 さらに default も指定されている場合、 その default には到達しないため warning となります。
// @lnsFront: ok
enum Val {
Val1,
Val2,
}
fn func( val:Val ) {
switch val {
case .Val1 {
return;
}
case .Val2 {
return;
}
default { // warning : ここには到達しない
return;
}
}
}
fail safe default
上記の通り、 全ての enum 値に対する case が指定されていて、 さらに default も指定されている場合、 その default には到達しないため warning となります。
しかし、 default を fail safe として使用している場合、 default を指定しておきたい時もあります。
そのような場合は、 default ではなく _default を指定することで、 warning を抑制できます。
// @lnsFront: ok
enum Val {
Val1,
Val2,
}
fn func( val:Val ) {
switch val {
case .Val1 {
return;
}
case .Val2 {
return;
}
_default { // ここには到達しないが、 warning は出力されない
return;
}
}
}
全 case 強制の switch
enum 値を条件にする switch において、 全ての enum 値に対する case を必ず宣言させたい時、 次のように _switch を使用できる。
// @lnsFront: ok
enum Val {
Val1,
Val2,
}
fn func( val:Val ) {
_switch val {
case .Val1 {
return;
}
case .Val2 {
return;
}
}
}
_switch では、 enum に対する case に抜けがあるとコンパイルエラーする。 また、 default は使用できない。
// @lnsFront: error
enum Val {
Val1,
Val2,
}
fn func( val:Val ) {
_switch val { // error
case .Val1 {
return;
}
}
}
_switch を利用することで、 enum 値 が開発途中で増えた際に、 switch-case 文の対応抜け漏れを確実に検出することができる。
match-case でも、同様に _match が利用可能である。
まとめ
LuneScript の一般分岐構文は、 if と switch があります。
goto はありません。
次回は、繰り返し制御について説明します。