値と型
LuneScript で扱う値と型について詳細に説明します。
プリミティブ型
| 型名 | 説明 | 例 |
|---|---|---|
int |
整数型 | 1, -10, 0x10 |
real |
実数型(浮動小数点数) | 1.0, 3.14 |
bool |
真偽値 | true, false |
str |
文字列(不変) | "hello", 'world' |
stem |
nil 以外の全ての型 | (任意の非 nil 値) |
stem は全ての型の基底となる型ですが、nil だけは保持できません。nil を許容するには stem!
を使用します。
コレクション
List<T> (リスト)
要素の追加・削除が可能な動的配列です。
let mut list: List<int> = [ 10, 20 ]; // 初期化
list.insert( 30 ); // 追加: [ 10, 20, 30 ]
list.remove(); // 末尾削除: [ 10, 20 ]
print( list[ 1 ] ); // アクセス (1-based index): 10
print( #list ); // サイズ取得: 2
Map<K,V> (連想配列)
キーと値のペアを保持します。JSON ライクなリテラルを使用できます。
let mut map: Map<str,int> = {
"a": 1,
"b": 2
};
// アクセス
print( map[ "a" ] ); // 1
print( map.b ); // 文字列キーならドットでもアクセス可
// 削除 (nil を代入)
map.a = nil;
nil が返るためです。
Set<T> (集合)
重複のない値の集合を管理します。リテラルは (@ ... ) です。
let mut set = (@ 1, 2, 3 );
set.add( 4 ); // 追加
set.del( 1 ); // 削除
print( set.has( 2 ) ); // 存在確認: true
print( set.len() ); // 要素数: 3
集合演算 or (和集合), and (積集合), sub (差集合) もサポートしています。
Nilable 型 (Null Safety)
型名の末尾に ! を付けることで、nil を保持可能な型になります。
let val1: int = 1; // nil 不可
let val2: int! = nil; // nil 可 (int or nil)
Nilable 型はそのままでは計算などに使用できません(安全のため)。必ず Unwrap (非 Nil化) する必要があります。
unwrap
強制的に nil を取り除きます。値が nil の場合は実行時エラーになります。
let a: int! = 10;
let b: int = unwrap a;
安全に unwrap するために default 値を指定できます。
let a: int! = nil;
let c: int = unwrap a default 0; // nil なら 0 になる
if! let / when!
変数が nil でない場合のみブロックを実行する構文です。
fn funcReturnsNilable(): int! { return 1; }
if! let x = funcReturnsNilable() {
// x はここでは非 nil (int) として扱える
print( x + 1 );
} else {
print( "x was nil" );
}
when! は既存の変数が nil かどうかをチェックします。
let val: int! = nil;
when! val {
// このブロック内では val は int 型 (immutable)
}
let! .. then ..
「変数が nil の場合の処理」を先に記述するスタイルです(Guard 節に近い使い方)。
fn funcReturnsNilable(): int! { return nil; }
let! x = funcReturnsNilable() {
// x が nil の場合に実行される
return;
}
// ここでは x は非 nil
print( x + 1 );
Nil 条件演算子 ($)
nilable な値に対し、nil でない場合のみメンバアクセスや関数呼び出しを行います。値が nil の場合は nil を返します。評価結果は常に Nilable 型になります。
- メンバアクセス:
obj$.member - 索引アクセス:
obj$[index] - 関数呼び出し:
func$(args)
class Test {
pub let val: List<int>;
pub fn func(): int { return 100; }
}
fn sub( test: Test! ) {
// test が nil ならすべて nil になる
print( test$.val$[1], test$.func$() );
}
sub( new Test( [ 1, 2 ] ) ); // 1 100
sub( nil ); // nil nil
キャスト
型変換には @@ (強制) と @@@ (安全) があります。
強制キャスト (@@)
let val: stem = 10;
let i = val@@int; // チェックなしで変換。失敗時の動作は未定義またはエラー。
安全なキャスト (@@@)
let val: stem = "test";
if! let i = val@@@int {
print( "Integer!" );
} else {
print( "Not an integer" );
}
変換できない場合は nil が返ります。
Algebric Data Type (代数的データ型)
alge は列挙型の一種ですが、各値 (コンストラクタ) がパラメータを持つことができます。直和型 (Tagged Union) です。
alge Shape {
Rect( real, real ),
Circle( real ),
}
let s = Shape.Rect( 10.0, 20.0 );
match s {
case .Rect( w, h ) { print( "Rect:", w * h ); }
case .Circle( r ) { print( "Circle:", r * r * 3.14 ); }
}
Enum (列挙型)
単純な値の列挙です。整数、実数、文字列を割り当てることができます。
enum Color {
Red = 0,
Green, // 1 (自動付番)
Blue, // 2
}
print( Color.Red ); // 0
print( Color.Red.$_txt ); // "Color.Red" (文字列表現)
生の値から Enum への変換には _from を使います。
enum Color { Green=1 }
let c = unwrap Color._from( 1 ); // Color.Green (nilable なので unwrap が必要)
Tuple (タプル)
複数の値をまとめて扱います。
let t: (int, str) = (= 1, "ok" );
関数への引数渡しなどで展開するには ... を使います。
fn func( i: int, s: str ) { print( i, s ); }
let t: (int, str) = (= 1, "ok" );
func( t... );