vec
目的
Vec<.T>を提供 し、push/get/pop/setなどの基本 操作 を共通 API として使 えるようにします。alloc/collectionsの他 の構造 が依存 する基礎 配列 として機能 します。
実装
Vec<.T>はlen/cap/dataを持 つ struct で、dataはMemPtr<.T>として管理 します。pushで容量 不足 が起 きた場合 は 2倍 へ拡張 し、typedrealloc_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 1Vec
目的
要素数 ・容量 ・要素 領域 の先頭 を保持 し、alloc/collectionsの他 API から共通 に扱 えるようにします。
実装
lenとcapはi32、dataはMemPtr<.T>で保持 します。実体 の配列 はヒープ上 の連続 領域 です。
注意
Vec<.T>自体 はdata領域 の所有権 を持 ちます。再確保 によりdataの番地 が変 わるため、生 アドレスを長期 に保持 してはいけません。
計算量
- struct
自体 の読 み書 きは O(1) です。
VecDataLen
Vec<.T> の data/len をまとめて
目的
内部 バッファ先頭 と要素数 を 1回 の呼 び出 しで扱 えるようにします。- sort
系 helper のように data と len を対 で読む API で、.Pairに頼 らず明示的 な field名 を与 えます。
実装
dataはMemPtr<.T>、lenはi32を保持 します。
注意
dataはVec<.T>の内部 領域 を指 すため、再確保 が起 きると無効 になります。lenは取得時点 の値 であり、その後 の変更 には追従 しません。
計算量
- struct
自体 の生成 と field読 み取 りは O(1) です。
vec_new
Vec<.T> を
目的
空 のVec<.T>を返 し、push連鎖 の起点 として使 えるようにします。
実装
初期 容量 を 8 とし、その byte数 だけ typedalloc_ptr<.T>で確保 します。len = 0、cap = 8、data = 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 1vec_with_capacity
Vec<.T> を
目的
事前 に必要 な容量 が分 かっている場面 で、再確保 を減 らしたVec<.T>を作 ります。
実装
指定 したcapに応 じて typedalloc_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 1vec_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 1vec_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 1vec_data_ptr
目的
既存 API との互換 のため、MemPtr<.T>の番地 をi32として取 り出 します。
実装
- field
dataのMemPtr<.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 1vec_data_mem_ptr
MemPtr<.T> として
目的
alloc/collections内部 でVec<.T>の要素 領域 を型付きポインタとして安全 に扱 えるようにします。
実装
- field
dataをそのまま返 します。
注意
主 に stdlib内部 の実装 補助 を想定 した API です。再確保 が起 きると pointer は無効化 されうるので、長期 保持 は避 けます。
計算量
時間 計算量 は O(1) です。
vec_data_len
目的
- sort
系 helper のようにdataとlenを同時 に使 う処理 で、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>からdataとlenを取 り出 し、VecDataLen<.T>として返 します。
注意
dataはMemPtr<.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 1vec_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 1vec_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:
1vec_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;
0vec_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;
0vec_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 1vec_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;
0new: 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