tech

[English] [Japanese]

25. Cast

LuneScript offers three types of casting.

  • @@
  • @@@
  • @@=

@@

@@ forces a type conversion without checking the type of the source value at runtime.

// @lnsFront: ok
let val1:stem = 1;
let val2:int = val1@@int;

Forced casting can also be performed on values that cannot be converted originally, such as the following.

// @lnsFront: ok
let val1:stem = 1;
let val2:str[] = val1@@str[];
print( #val2 ); // runtime error

The above assigns the value 1 of type int to val1 of type stem and casts it to val2 of type str list. In other words, you cast the int type to a str list. Accessing this val2 will result in a runtime error.

Note that if you explicitly cast something that can be type-converted implicitly with @@ , a warning will occur.

For example, func( "abc"@@stem ) in the following sample prints a warning because the string "abc" can be converted to stem without an explicit cast.

// @lnsFront: ok
fn func( val:stem ) {
}
func( "abc"@@stem );

Also, an apparently illegal type conversion will result in a compilation error.

For example, in the following case, 1@@str is converted from int to str, but since this type conversion is not possible, a compilation error occurs.

// @lnsFront: error
let val = "abc"@@int;  // error
let val2 = 1@@str;  // error

A @@ cast to a class type prints a warning.

@@ cannot cast from nilable to non-nilable.

Use @@@ or @@= for casting to class types.

@@@

@@@ dynamically checks the type of the conversion source and performs type conversion.

Here is an example for @@@.

// @lnsFront: ok
fn func( val:stem ) {
   if! val@@@int {
      print( "int:%d" ( _exp ) );
   }
   if! val@@@str {
      print( "str:%s" ( _exp ) );
   }
}
func( 1 ); // int:1
func( "abc" ); // str:abc

val@@@int checks the type of val, converts it if it is int type, and returns nil if it is not int type. Also, val@@@str checks the type of val, converts it if it is str type, and returns nil if it is not str type.

This causes func( 1 ) to print int:1 and func( "abc" ) to print str:abc.

@@@ is castable even if the caster is nilable.

Restriction 1 for @@@

A @@@ cast from a value of type real to an int should return nil, but there are cases where it succeeds.

That case is when a value of type real with no decimal places is cast to int.

Originally, a @@@ cast from a value of type real to int should return nil, but this is a current limitation.

Note that when transpiling to Go language, @@@ casting from a real type value to int returns nil as per the original specification.

This behavior is subject to change in the future.

For example, the following func( 1 ) outputs int:1 , real:1 , and func( 2.5 ) outputs real:2.5 .

// @lnsFront: ok
fn func( val:stem ) {
   if! val@@@int {
      print( "int:%d" ( _exp ) );
   }
   if! val@@@real {
      print( "real:%g" ( _exp ) );
   }
}
func( 1.0 );
func( 2.5 );

Restriction 2 of @@@

@@@ is only available for int/real/str/class/interface.

You can't use enum etc.

Also, generics are not available in class either.

@@=

@@= is used when converting classes without methods. A compile error will occur if you specify a class that has a method or something other than a class.

Note that @@= also performs type conversion forcibly without checking the original value.

@@= should only be used when type checking is slow.

summary

Casts should be avoided as much as possible, except for conversions between int and real. By using generics, alge, etc., you can create general-purpose processing while keeping the type.

Even if you use cast, please use @@@ and design to minimize the use of @@ and @@=.