Vector
vector<T>
は、Moveが提供する唯一のプリミティブコレクション型です。vector<T>
は、値を「末尾」からプッシュ/ポップすることで拡大または縮小できるT
の同質コレクションです。
vector<T>
は任意のT
型でインスタンス化出来ます。例えばvector<u64>
、vector<address>
、vector<0x42::MyModule::MyResource>
、vector<vector<u8>>
は全て有効なベクトル型です。
リテラル
一般的なベクター
リテラル
vector
リテラルを使用して、任意の型のベクターを作成出来ます。
構文 | 型 | 説明 |
---|---|---|
vector[] | T が単一であるvector[]: vector<T> , 非参照型 | 空のベクター |
vector[e1, ..., en] | e_i: T s.t. 0 < i <= n でありn > 0 であるvector[e1, ..., en]: vector<T> | (長さn の)n 要素を持つベクター |
この場合、vector
の型は要素の型またはベクターの使用法から推測されます。 型を推測できない場合、または単にわかりやすくするため、型を明示的に指定出来ます。
vector<T>[]: vector<T>
vector<T>[e1, ..., en]: vector<T>
ベクターリテラルの例
script {
fun example() {
(vector[]: vector<bool>);
(vector[0u8, 1u8, 2u8]: vector<u8>);
(vector<u128>[]: vector<u128>);
(vector<address>[@0x42, @0x100]: vector<address>);
}
}
vector<u8>
リテラル
Moveでのベクターの一般的な使用事例はvector<u8>
で表される「バイト配列」を表す事です。これらの値は、公開鍵やハッシュ結果等の暗号化目的でよく使用されます。これらの値は非常に一般的なので、個々のu8
値が数値形式で指定されるvector[]
を使用するのとは対照的に、値をより読みやすくするための特定の構文が提供されています。
現在サポートされているvector<u8>
リテラルの種類は、 バイト文字列 と 16進文字列 の2種類です。
バイト文字列
バイト文字列は、b
で始まる引用符で囲まれた文字列リテ ラルです (例:b"Hello!\n"
)
これらはエスケープシーケンスを許可する ASCIIエンコードされた文字列です。現在サポートされているエスケープシーケンスは:
エスケープシーケンス | 説明 |
---|---|
\n | 改行 |
\r | キャリッジリターン |
\t | タブ |
\\ | バックスラッシュ |
\0 | ヌル |
\" | 引用 |
\xHH | 16進エスケープ、16進バイトシーケンスHH を挿入します |
16進文字列
16進文字列はx
で始まる引用符で囲まれた文字列リテラルです (x例:x"48656C6C6F210A"
)
00
からFF
までの各バイトペアは、16進数でエンコードされたu8
値として解釈されます。従って、各バイトペアは、結果のvector<u8>
内のひとつのエントリに対応します。
文字列リテラルの例
script {
fun byte_and_hex_strings() {
assert!(b"" == x"", 0);
assert!(b"Hello!\n" == x"48656C6C6F210A", 1);
assert!(b"\x48\x65\x6C\x6C\x6F\x21\x0A" == x"48656C6C6F210A", 2);
assert!(
b"\"Hello\tworld!\"\n \r \\Null=\0" ==
x"2248656C6C6F09776F726C6421220A200D205C4E756C6C3D00",
3
);
}
}
演算
以下に示すように、vector
はMove標準ライブラリのstd::vector
モジュールを介していくつかの演算を提供します。時間の経過で操作が追加される可能性が有ります。vector
の最新のドキュメントは、こちらで見つかります。
関数 | 説明 | 中止? |
---|---|---|
vector::empty<T>(): vector<T> | T 型の値を保存出来る空のベクターを作成します。 | 一度も無い |
vector::is_empty<T>(): bool | ベクトルv に要素がない場合はtrue を返し、そうでない場合はfalse を返します | 一度もない |
vector::singleton<T>(t: T): vector<T> | t を含むサイズ1のベクトルを作成する | 一度もない |
vector::length<T>(v: &vector<T>): u64 | ベクターv の長さを返す | 一度もない |
vector::push_back<T>(v: &mut vector<T>, t: T) | v の末尾へt を追加 | 一度もない |
vector::pop_back<T>(v: &mut vector<T>): T | v の最後の要素を削除して返す | v が空の場合 |
vector::borrow<T>(v: &vector<T>, i: u64): &T | インデックスi でT への不変参照を返す | 境界内 でi がない場合 |
vector::borrow_mut<T>(v: &mut vector<T>, i: u64): &mut T | インデックスi でT への可変参照を返す | 境界内でi がない場合 |
vector::destroy_empty<T>(v: vector<T>) | v を消去 | v が空でない場合 |
vector::append<T>(v1: &mut vector<T>, v2: vector<T>) | v1 の末尾へv2 の要素を追加します | 一度もない |
vector::reverse_append<T>(lhs: &mut vector<T>, other: vector<T>) | other ベクターの全ての要素をlhs ベクター内へ逆順でプッシュする(other で起きた時の逆順) | 一度もない |
vector::contains<T>(v: &vector<T>, e: &T): bool | e がベクトルv 内にある場合はtrueを返します。そうでない場合はfalseを返します。 | 一度もない |
vector::swap<T>(v: &mut vector<T>, i: u64, j: u64) | ベクトルv のii 番めとj 番めのインデックスの要素を交換します。 | i またはがj 範囲外の場合 |
vector::reverse<T>(v: &mut vector<T>) | ベクトルv 内の要素の順序を逆にする | 一度もない |
vector::reverse_slice<T>(v: &mut vector<T>, l: u64, r: u64) | ベクターv 内の要素[l, r) の順序を逆で配置する | 一度もない |
vector::index_of<T>(v: &vector<T>, e: &T): (bool, u64) | e がイン デックスi のベクターv にある場合は(true, i) を返します。そうでない場合は(false, 0) を返します。 | 一度もない |
vector::insert<T>(v: &mut vector<T>, i: u64, e: T) | O(length - i) 時間を使用して、0 <= i <= length 位置へ新しい要素e を挿入します。 | i が範囲外の場合 |
vector::remove<T>(v: &mut vector<T>, i: u64): T | ベクターv のi 番目の要素を削除し、後続の要素を全てシフトします。これは O(n) で、ベクター内の要素の順序は保持されます。 | i が範囲外の場合 |
vector::swap_remove<T>(v: &mut vector<T>, i: u64): T | ベクターv のi 番目の要素を最後の要素と交換し、要素をポップします。これは O(1) ですが、ベクター内の要素の順序は保持されません | i が範囲外の場合 |
vector::trim<T>(v: &mut vector<T>, new_len: u64): u64 | ベクターv を小さいサイズのnew_len へトリミングし、削除された要素を順に返します。 | new_len はv の長さより大きい |
vector::trim_reverse<T>(v: &mut vector<T>, new_len: u64): u64 | ベクターv を小さいサイズのnew_len へトリミングし、削除された要素を逆順で返します。 | new_len はv の長さより大きい |
vector::rotate<T>(v: &mut vector<T>, rot: u64): u64 | rotate(&mut [1, 2, 3, 4, 5], 2) -> [3, 4, 5, 1, 2] を指定すると、分割 ポイント(この例では3)を返します。 | 一度もない |
vector::rotate_slice<T>(v: &mut vector<T>, left: u64, rot: u64, right: u64): u64 | rotate a slice [left, right) with left <= rot <= right in place, returns the split point left <= rot <= right の位置でスライス[left, right) を回転し、分割点を返します。 | 一度もない |
例
script {
use std::vector;
let v = vector::empty<u64>();
vector::push_back(&mut v, 5);
vector::push_back(&mut v, 6);
assert!(*vector::borrow(&v, 0) == 5, 42);
assert!(*vector::borrow(&v, 1) == 6, 42);
assert!(vector::pop_back(&mut v) == 6, 42);
assert!(vector::pop_back(&mut v) == 5, 42);
}
ベクターの破壊とコピー
vector<T>
の一部の動作は、要素型の機能T
に依存します。例えばdrop
を持たない要素を含むベクトルは、上記例のv
のような暗黙的破棄が出来ません。vector::destroy_empty
で明白に破棄する必要が有ります。
注意:vec
が要素を含んでいない場合を除きvector::destroy_empty
は実行時に中止します。
fun destroy_any_vector<T>(vec: vector<T>) {
vector::destroy_empty(vec) // この行を削除するとコンパイラエラーが発生します
}
ただし、drop
の要素を含むベクターを削除してもエラーは発生しません。
script {
fun destroy_droppable_vector<T: drop>(vec: vector<T>) {
// 有効!
// ベクターを破棄するために何もする必要は有りません
}
}
ベクターは要素型がcopy
を持たない限りコピーできません。言い換えると、T
が copy
を持つ場合のみ、vector<T>
はcopy
を持ちます。
所有権
上記のように、要素がコピー出来る場合のみvector
要素はコピー出来ます。