tech

[English] [Japanese]

08. General branch syntax

This time I will explain the general branching syntax of LuneScript.

Syntax list

LuneScript supports the following general branching syntax.

  • if
  • switch

By the way, the reason why I dare to call it "general" branch control here is that there is separate branch control in nilable control.

if

The if statement is used like this:

// @lnsFront: ok
let val = 1;
if val == 1 {
   print( "hoge" );
}
elseif val == 2 {
   print( "foo" );
}
else {
   print( "bar" );
}

I don't think it needs explanation, but it is processed as follows.

  • If the if expression is true, the if block is executed.
  • If the if expression is false and the elseif expression is true, the elseif block is executed.
  • If all the expressions fail, the else block is executed.
  • Multiple elseif may exist.
  • elseif and else may not exist.
  • The condition that the expression is "failed" is when the result of the expression is nil or false.

Comparing with a bool value

LuneScript discourages comparisons with bool values.

Specifically, we do not recommend the following operations:

// @lnsFront: ok
   let val1 = true;
   if val1 == true {
   }
   if val1 == false {
   }
   if val1 ~= false {
   }
   if val1 ~= true {
   }

The above operations will be deprecated in the near future.

Now prints a warning message when compiling.

If you want to switch processing depending on bool true/false value, please do as follows.

// @lnsFront: ok
let exp = true;
if exp {
   print( "exp is true" );
}
else {
   print( "exp is false" );
}
if not exp {
   print( "exp is false" );
}

switch

Use the switch statement like this:

// @lnsFront: ok
let val = 1;
switch val {
   case 1 {
      print( "hoge" );
   }
   case 2 {
      print( "foo" );
   }
   default {
      print( "bar" );
   }
}

Note that this sample is synonymous with the if sample above.

You can write multiple expressions in the case of a switch like this:

// @lnsFront: ok
let val = 1;
switch val {
   case 10, 20, 30 {
      print( "hoge" );
   }
   default {
      print( "bar" );
   }
}

This is synonymous with the following if statement, which executes that block if any value is matched.

// @lnsFront: ok
let val = 1;
if val == 10 or val == 20 or val == 30 {
   print( "hoge" );
}
else {
   print( "bar" );
}

The point to be noted with the switch statement is that break is not required unlike C language.

For example, the following break will exit the for statement instead of exiting the switch statement.

// @lnsFront: ok
for count = 1, 10 {
   switch count {
      case 5 {
         break;
      }
   }
}

Flow analysis of enum values

If the switch condition is an enum value, flow analysis is performed by checking whether all enum values are specified in the case statement.

For example, in the following case, the print() statement after the switch statement within the func() function will result in an unreachable error. This is because return is specified for all the values ( Val1, Val2 ) cases of the enum value Val .

// @lnsFront: error
enum Val {
   Val1,
   Val2,
}
fn func( val:Val ) {
   switch val {
      case .Val1 {
         return;
      }
      case .Val2 {
         return;
      }
   }
   print( work ); // error : 全ての enum 値の case があり、 return している
}

Also, if case is specified for all enum values and default is also specified, the default will not be reached, resulting in a 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

As mentioned above, if case is specified for all enum values and default is also specified, the default will not be reached, resulting in a warning.

But sometimes you want to specify default if you use default as fail safe.

In such cases, you can suppress the warning by specifying _default instead of default .

// @lnsFront: ok
enum Val {
   Val1,
   Val2,
}
fn func( val:Val ) {
   switch val {
      case .Val1 {
         return;
      }
      case .Val2 {
         return;
      }
      _default { // ここには到達しないが、 warning は出力されない
         return;
      }
   }
}

all-case-enforced switch

In a switch conditional on an enum value, when you want to be sure to declare a case for all enum values, you can use _switch as follows.

// @lnsFront: ok
enum Val {
   Val1,
   Val2,
}
fn func( val:Val ) {
   _switch val {
      case .Val1 {
         return;
      }
      case .Val2 {
         return;
      }
   }
}

In _switch, if there is a missing case for enum, a compilation error will occur. Also default is not available.

// @lnsFront: error
enum Val {
   Val1,
   Val2,
}
fn func( val:Val ) {
   _switch val { // error
      case .Val1 {
         return;
      }
   }
}

By using _switch, when the number of enum values increases during development, omissions in switch-case statements can be reliably detected.

_match can be used in match-case as well.

summary

Common branching syntaxes in LuneScript are if and switch.

There are no gotos.

Next time, I will explain the repeat control.