NEPLg2 Standard Library - vec - vec
Web Playground
Web Playground

vec

連続れんぞくメモリをもちいる可変長かへんちょう配列はいれつ

目的もくてき

  • Vec<.T>提供ていきょうし、push / get / pop / set などの基本きほん操作そうさ共通きょうつう API として使つかえるようにします。
  • alloc/collectionsほか構造こうぞう依存いそんする基礎きそ配列はいれつとして機能きのうします。

実装じっそう

  • Vec<.T>len / cap / dataつ struct で、dataMemPtr<.T> として管理かんりします。
  • push容量ようりょう不足ぶそくきた場合ばあいは 2 ばい拡張かくちょうし、typed realloc_ptr再配置さいはいちします。

注意ちゅうい

  • get / pop存在そんざいしない位置いちOption::Noneかえします。
  • set範囲外はんいがいでは失敗しっぱいにせず、そのままの Vec<.T>かえします。
  • 再確保さいかくほきると内部ないぶバッファの番地ばんちわりえます。

計算量けいさんりょう

  • get / set / len / cap / is_empty は O(1) です。
  • push償却しょうきゃく O(1)、拡張かくちょう発生時はっせいじ最悪さいあく時間じかん計算量けいさんりょうは O(n) です。

使用例しようれい

TEST
#entry main
#target std
#import "std/test" as *
#import "alloc/collections/vec" as *
fn main <()*>()> ():
    assert_eq_i32 0 vec_len new<i32>;
    let a2 <Vec<i32>>:
        new<i32>
        |> push 10
        |> push 20
    assert_eq_i32 2 vec_len a2;
    let b2 <Vec<i32>>:
        new<i32>
        |> push 10
        |> push 20
    match vec_get<i32> b2 1:
        Option::Some x:
            assert_eq_i32 20 x;
        Option::None:
            assert false;
TEST
#entry main
#target std
#import "std/test" as *
#import "alloc/collections/vec" as *
fn main <()*>()> ():
    let v2 <Vec<i32>>:
        vec_with_capacity<i32> 2
        |> push 1
        |> push 2
    match vec_get<i32> v2 0:
        Option::Some x:
            assert_eq_i32 1 x;
        Option::None:
            assert false;
    let w2 <Vec<i32>>:
        vec_with_capacity<i32> 2
        |> push 1
        |> push 2
    assert is_none<i32> vec_get<i32> w2 3;
TEST
#entry main
#target std
#import "alloc/collections/vec" as *
fn main <()*>i32> ():
    let cleared <Vec<i32>>:
        new<i32>
        |> push 11
        |> push 22
        |> vec_clear<i32>
    if eq vec_len cleared 0 0 1

Vec

可変長かへんちょう配列はいれつ本体ほんたい

目的もくてき

  • 要素数ようそすう容量ようりょう要素ようそ領域りょういき先頭せんとう保持ほじし、alloc/collectionsほか API から共通きょうつうあつかえるようにします。

実装じっそう

  • lencapi32dataMemPtr<.T>保持ほじします。
  • 実体じったい配列はいれつはヒープじょう連続れんぞく領域りょういきです。

注意ちゅうい

  • Vec<.T> 自体じたいdata 領域りょういき所有権しょゆうけんちます。
  • 再確保さいかくほにより data番地ばんちわるため、なまアドレスを長期ちょうき保持ほじしてはいけません。

計算量けいさんりょう

  • struct 自体じたいきは O(1) です。

VecDataLen

Vec<.T> の data/len をまとめてかえ軽量けいりょう struct

目的もくてき

  • 内部ないぶバッファ先頭せんとう要素数ようそすうを 1 かいしであつかえるようにします。
  • sort けい helper のように data と len をつい読むよむ API で、.Pairたよらず明示的めいじてきな field めいあたえます。

実装じっそう

  • dataMemPtr<.T>leni32保持ほじします。

注意ちゅうい

  • dataVec<.T>内部ないぶ領域りょういきすため、再確保さいかくほきると無効むこうになります。
  • len取得時点しゅとくじてんあたいであり、そのあと変更へんこうには追従ついじゅうしません。

計算量けいさんりょう

  • struct 自体じたい生成せいせいと field りは O(1) です。

vec_new

既定きてい容量ようりょうから Vec<.T>つく

目的もくてき

  • からVec<.T>かえし、push 連鎖れんさ起点きてんとして使つかえるようにします。

実装じっそう

  • 初期しょき容量ようりょうを 8 とし、その byte すうだけ typed alloc_ptr<.T>確保かくほします。
  • len = 0cap = 8data = allocated pointer の struct をかえします。

注意ちゅうい

  • 初期しょき容量ようりょう固定値こていち 8 です。
  • 確保かくほ失敗しっぱいunwrap_ok により到達不能とうたつふのうになります。Vec 生成せいせいResult 化するかどうかは reboot 後続こうぞく整理せいりします。

計算量けいさんりょう

  • 時間じかん計算量けいさんりょうは O(1)、追加ついか空間くうかん計算量けいさんりょうも O(1) です。

使用例しようれい

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
fn main <()*>i32> ():
    let v new<i32>;
    if eq vec_len<i32> v 0 0 1

vec_with_capacity

初期しょき容量ようりょう指定していして Vec<.T>つく

目的もくてき

  • 事前じぜん必要ひつよう容量ようりょうかっている場面ばめんで、再確保さいかくほらした Vec<.T>つくります。

実装じっそう

  • 指定していした capおうじて typed alloc_ptr<.T>び、len = 0かえします。

注意ちゅうい

  • cap = 0 でも動作どうさします。
  • 確保かくほ失敗しっぱいunwrap_ok により到達不能とうたつふのうになります。

計算量けいさんりょう

  • 時間じかん計算量けいさんりょうは O(1) です。

使用例しようれい

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
fn main <()*>i32> ():
    let v vec_with_capacity<i32> 16;
    if eq vec_cap<i32> v 16 0 1

vec_len

要素数ようそすうかえ

目的もくてき

  • Vec<.T>現在げんざい何個なんこ要素ようそはいっているかをかえします。

実装じっそう

  • struct field len をそのままかえします。

注意ちゅうい

  • 変更へんこうともなわないり API です。

計算量けいさんりょう

  • 時間じかん計算量けいさんりょうは O(1) です。

使用例しようれい

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
fn main <()*>i32> ():
    let v0 new<i32>;
    let v1 push v0 3;
    if eq vec_len<i32> v1 1 0 1

vec_cap

容量ようりょうかえ

目的もくてき

  • 現在げんざい確保かくほされている要素数ようそすうぶんの容量ようりょうかえします。

実装じっそう

  • struct field cap をそのままかえします。

注意ちゅうい

  • 変更へんこうともなわないり API です。

計算量けいさんりょう

  • 時間じかん計算量けいさんりょうは O(1) です。

使用例しようれい

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
fn main <()*>i32> ():
    let v new<i32>;
    if gt vec_cap<i32> v 0 0 1

vec_data_ptr

内部ないぶデータ領域りょういきの raw address をかえ

目的もくてき

  • 既存きぞん API との互換ごかんのため、MemPtr<.T>番地ばんちi32 としてします。

実装じっそう

  • field dataMemPtr<.T>mem_ptr_addr で raw address にもどします。

注意ちゅうい

  • かえあたいなまアドレスなので、範囲はんい寿命じゅみょう再確保さいかくほがわ管理かんりする必要ひつようがあります。
  • 新規しんきコードでは、できるだけ vec_data_mem_ptr優先ゆうせんします。

計算量けいさんりょう

  • 時間じかん計算量けいさんりょうは O(1) です。

使用例しようれい

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
fn main <()*>i32> ():
    let v new<i32>;
    if gt vec_data_ptr<i32> v 0 0 1

vec_data_mem_ptr

内部ないぶデータ領域りょういきMemPtr<.T> としてかえ

目的もくてき

  • alloc/collections 内部ないぶVec<.T>要素ようそ領域りょういきを型付きポインタとして安全あんぜんあつかえるようにします。

実装じっそう

  • field data をそのままかえします。

注意ちゅうい

  • おもに stdlib 内部ないぶ実装じっそう補助ほじょ想定そうていした API です。
  • 再確保さいかくほきると pointer は無効化むこうかされうるので、長期ちょうき保持ほじけます。

計算量けいさんりょう

  • 時間じかん計算量けいさんりょうは O(1) です。

vec_data_len

内部ないぶバッファ先頭せんとう要素数ようそすう同時どうじかえ

目的もくてき

  • sort けい helper のように datalen同時どうじ使つか処理しょりで、field めいつきの struct をられるようにします。

使用例しようれい

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
#import "core/field" as *
fn main <()*>i32> ():
    let v0 new<i32>;
    let v1 push v0 7;
    let s vec_data_len<i32> v1;
    if and gt mem_ptr_addr get s "data" 0 eq get s "len" 1 0 1

実装じっそう

  • Vec<.T> から datalenし、VecDataLen<.T> としてかえします。

注意ちゅうい

  • dataMemPtr<.T> なので、なまアドレスが必要ひつよう場合ばあいmem_ptr_addrとおします。

計算量けいさんりょう

  • 時間じかん計算量けいさんりょうは O(1) です。

vec_is_empty: 空か判定する

目的:

  • len が 0 なら true を返します。

実装(アルゴリズム):

  • len == 0 を判定します。

注意(重要):

  • 変更操作ではありません。

計算量:

  • O(1)

使い方:

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
fn main <()*>i32> ():
    let v new<i32>;
    if vec_is_empty<i32> v 0 1

vec_push: 末尾に要素を追加する

目的:

  • item を末尾に追加し、新しい Vec を返します。

実装(アルゴリズム):

  • 容量不足なら 2 倍に拡張して realloc します。

注意(重要):

  • 返り値の Vec を受け取り直してください。

計算量:

  • ならし O(1)

使い方:

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
fn main <()*>i32> ():
    let v0 new<i32>;
    let v1 push v0 7;
    if eq vec_len<i32> v1 1 0 1

vec_get: 要素を取得する

目的:

  • idx が範囲内なら Some、範囲外なら None を返します。

実装(アルゴリズム):

  • idx の範囲を判定し、要素を load します。

注意(重要):

  • idx が負のときも None です。

計算量:

  • O(1)

使い方:

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
#import "core/option" as *
fn main <()*>i32> ():
    let v0 new<i32>;
    let v1 push v0 9;
    match vec_get<i32> v1 0:
        Option::Some x:
            if eq x 9 0 1
        Option::None:
            1

vec_set: 要素を上書きする(範囲外は無視)

目的:

  • idx が範囲内なら値を上書きします。

実装(アルゴリズム):

  • idx の範囲を判定し、範囲内のみ store します。

注意(重要):

  • 範囲外は何もしません。

計算量:

  • O(1)

使い方:

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
#import "core/option" as *
fn main <()*>i32> ():
    let v0 new<i32>;
    let v1 push v0 1;
    vec_set<i32> v1 0 5;
    0

vec_pop: 末尾要素を取り出す

目的:

  • 末尾要素を返し、長さを 1 減らします。

実装(アルゴリズム):

  • len==0 なら None、そうでなければ最後の要素を load します。

注意(重要):

  • 返り値は (Vec, Option) のタプルです。

計算量:

  • O(1)

使い方:

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
#import "core/option" as *
fn main <()*>i32> ():
    let v0 new<i32>;
    let v1 push v0 4;
    let p vec_pop<i32> v1;
    0

vec_clear: すべての要素を削除する

目的:

  • len を 0 にして空にします。

実装(アルゴリズム):

  • data はそのままに len だけを 0 にします。

注意(重要):

  • メモリは解放されません。

計算量:

  • O(1)

使い方:

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
fn main <()*>i32> ():
    let v0 new<i32>;
    let v1 push v0 1;
    let v2 vec_clear<i32> v1;
    if eq vec_len<i32> v2 0 0 1

vec_free: メモリを解放する

目的:

  • data を解放します。

実装(アルゴリズム):

  • cap サイズ分の領域を dealloc します。

注意(重要):

  • Vec 自体は値なので解放不要です。

計算量:

  • O(1)

使い方:

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
fn main <()*>i32> ():
    let v new<i32>;
    vec_free<i32> v;
    0

new: vec_new の短縮エイリアス
len: vec_len の短縮エイリアス
cap: vec_cap の短縮エイリアス
push: vec_push の短縮エイリアス

目的:

  • パイプ演算子と組み合わせた記述を簡潔にします。

実装(アルゴリズム):

  • vec_push をそのまま再公開します。

注意(重要):

  • シグネチャは vec_push と同じです。

計算量:

  • ならし O(1)

使い方:

TEST
#entry main
#target std
#import "alloc/collections/vec" as *
fn main <()*>i32> ():
    let v:
        new<i32>
        |> push 1
        |> push 2
    if eq len<i32> v 2 0 1