ジェネリクス

型をパラメータとして受け取る汎用コードの書き方を学びます。


現行の対応状況(v0.2.0)

現行仕様(v0.2.0)

Vec2<T> のようなジェネリクス構造体、fn identity<T>(...) -> T のようなジェネリック関数、(A, B) のようなタプルは未実装/未検証です。型パラメータは List<i32> など一部の組み込みで限定的にしか使えません。実際の開発では具体的な型で定義してください。

実際に推奨される書き方

構造体は具体的な型で定義し、複数の型に対応したい場合は型ごとに構造体を分けます。

filename.ngs
struct Vec2i {
    x: i32
    y: i32
}

struct Vec2f {
    x: f64
    y: f64
}

impl Vec2i {
    fn sum(self: Vec2i) -> i32 {
        return self.x + self.y
    }
}

fn main() {
    val a = Vec2i { x: 1, y: 2 }
    println(a.sum())  // 3
}

List / Rc の既知バグ

既知バグ(v0.2.0)

List<T> は List.new() / push / len / get / set という API はありますが、LLVM コード生成時に zext i64 to i64 エラーが発生しリンクに失敗する既知バグがあります。Rc.new(値) / .get() も API としては存在しますが、.get() の戻り値が意図と異なる場合があります。当面は構造体 + 値渡しを推奨します。


Result / Option の代用

ジェネリクスではなく具体的な enum で自作します。

filename.ngs
enum MathResult {
    Value(f64)
    DivByZero
}

fn divide(a: f64, b: f64) -> MathResult {
    if b == 0.0 {
        return MathResult.DivByZero()
    }
    return MathResult.Value(a / b)
}

fn main() {
    val r = divide(10.0, 3.0)
    match r {
        Value(v) => println("ok"),
        DivByZero => println("error"),
    }
}

ロードマップ

以下の機能は将来のバージョンで予定されているものです。