English

値と型

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
LuneScript (および Lua) のリストインデックスは 1 から始まります。範囲外アクセスは未定義動作となるため注意してください。

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;
Map へのアクセス結果は常に Nilable (T!) となります。キーに対応する値が存在しない場合 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 型になります。

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... );