メインコンテンツまでスキップ

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ヌル
\"引用
\xHH16進エスケープ、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>): Tvの最後の要素を削除して返すvが空の場合
vector::borrow<T>(v: &vector<T>, i: u64): &TインデックスiTへの不変参照を返す境界内でiがない場合
vector::borrow_mut<T>(v: &mut vector<T>, i: u64): &mut TインデックスiTへの可変参照を返す境界内で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): booleがベクトル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ベクターvi番目の要素を削除し、後続の要素を全てシフトします。これは O(n) で、ベクター内の要素の順序は保持されます。iが範囲外の場合
vector::swap_remove<T>(v: &mut vector<T>, i: u64): Tベクターvi番目の要素を最後の要素と交換し、要素をポップします。これは O(1) ですが、ベクター内の要素の順序は保持されませんiが範囲外の場合
vector::trim<T>(v: &mut vector<T>, new_len: u64): u64ベクターvを小さいサイズのnew_lenへトリミングし、削除された要素を順に返します。new_lenvの長さより大きい
vector::trim_reverse<T>(v: &mut vector<T>, new_len: u64): u64ベクターvを小さいサイズのnew_lenへトリミングし、削除された要素を逆順で返します。new_lenvの長さより大きい
vector::rotate<T>(v: &mut vector<T>, rot: u64): u64rotate(&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): u64rotate 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を持たない限りコピーできません。言い換えると、Tcopyを持つ場合のみ、vector<T>copyを持ちます。

詳細は型機能ジェネリクスのセクションを御覧下さい。

所有権

上記のように、要素がコピー出来る場合のみvector要素はコピー出来ます。