公開技術情報

[English] [Japanese]

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 はありません。

次回は、繰り返し制御について説明します。