[Aptos學習筆記#7]Move進階使用 - 使用Vector管理集合 - Managing Collections with Vector
目錄
- 為什麼需要Vector?
- Vector是什麼?
- 內聯 Vector 定義的十六進制數組與字符 - Hex and Bytestring literal for inline vector definitions
- Vector 速查表 - Vector Cheatsheet
一. 為什麼需要Vector?
前面的筆記中我們已經很熟悉結構體的類型了,它讓我們可以創建自己的類型並儲存複雜的數據,但有時候我們需要更動態、可擴展性核可管理性的功能,這邊Move提供了向量Vector的概念來處理
二. Vector是什麼?
- 用於儲存數據集合的內置類型( build-in type)
- 集合數據能夠是任何類型(但僅一種)
- Vector的功能實際上是由Move VM提供的
- 使用Vector唯一的辦法就是使用Move標準庫和native函數
script {
use 0x1::Vector;
fun main() {
// 使用泛型創建一個空的 Vector
let a = Vector::empty<u8>();
let i = 0;
// 將值塞入剛剛創建的Vector中
while (i < 10) {
Vector::push_back(&mut a, i);
i = i + 1;
};
// 現在印出Vector的長度
let a_len = Vector::length(&a);
0x1::Debug::print<u64>(&a_len);
// 移除掉兩個元素
Vector::pop_back(&mut a);
Vector::pop_back(&mut a);
// 再次印出Vector長度
let a_len = Vector::length(&a);
0x1::Debug::print<u64>(&a_len);
}
}
Vector最多可以儲存U64個單個非引用類型(single non-reference type)的值
例子: 為了理解Vector如何幫助管理巨大的存儲量,這邊撰寫一個模塊 ( Module )
module Shelf {
use 0x1::Vector;
struct Box<T> {
value: T
}
struct Shelf<T> {
boxes: vector<Box<T>>
}
public fun create_box<T>(value: T): Box<T> {
Box { value }
}
// 對於不可複製的內容本方法不可行
public fun value<T: copy>(box: &Box<T>): T {
*&box.value
}
public fun create<T>(): Shelf<T> {
Shelf {
boxes: Vector::empty<Box<T>>()
}
}
// 將Box的值移入Vector
public fun put<T>(shelf: &mut Shelf<T>, box: Box<T>) {
Vector::push_back<Box<T>>(&mut shelf.boxes, box);
}
// 將Vector中的元素移出
public fun remove<T>(shelf: &mut Shelf<T>): Box<T> {
Vector::pop_back<Box<T>>(&mut shelf.boxes)
}
// 計算Vector的長度
public fun size<T>(shelf: &Shelf<T>): u64 {
Vector::length<Box<T>>(&shelf.boxes)
}
}
在Script中,我們首先創建一個 Shelf,並為其提供幾個 Box,並觀察如何在Module中使用 Vector
script {
use {{sender}}::Shelf;
fun main() {
// 創建一個shelf和兩個u64類型的Box
let shelf = Shelf::create<u64>();
let box_1 = Shelf::create_box<u64>(99);
let box_2 = Shelf::create_box<u64>(999);
// 將剛剛創建的兩個Box推進Vector
Shelf::put(&mut shelf, box_1);
Shelf::put(&mut shelf, box_2);
// 印出長度 - 結果為2
0x1::Debug::print<u64>(&Shelf::size<u64>(&shelf));
// 拿走最後一個推進Vector的Box
let take_back = Shelf::remove(&mut shelf);
let value = Shelf::value<u64>(&take_back);
// 驗證我們拿出來的Box值是999
assert(value == 999, 1);
// 再次印出Vector長度 - 結果為1
0x1::Debug::print<u64>(&Shelf::size<u64>(&shelf));
}
}
Vector非常強大,它允許我們存儲大量數據(最大長度為 18,446,744,073,709,551,615),並讓我們在索引的存儲中使用它
三. 內聯 Vector 定義的十六進制數組與字符 - Hex and Bytestring literal for inline vector definitions
Vector也代表著表示字符串
VM 支援將vector<u8>當作參數傳遞給腳本中的主函數的方式
例子: 我們也可以在使用十六進制文本在Script或Module中定義一個vector<u8>
script {
use 0x1::Vector;
// 這是在main中傳入參數的方式
fun main(name: vector<u8>) {
let _ = name;
// 這是我們使用文字的方式
// 這邊表示的是一個hello world的字符串
let str = x"68656c6c6f20776f726c64";
// 十六進制的文字也傳給我們vector<u8>
Vector::length<u8>(&str);
}
}
有個簡單的方式就是使用字節串文字(bytestring literals)
script {
fun main() {
// 使用b"<我們想輸入的字符串>"的方式更簡易
let _ = b"hello world";
}
}
它們被當成是ASCII 字符串,也被表示為vector<u8>
四. Vector 速查表 - Vector Cheatsheet
在標準庫中的簡短Vector方法速查表
1.創建一個類型為<E>的空Vector
Vector::empty<E>(): vector<E>;
2.取得Vector長度
Vector::length<E>(v: &vector<E>): u64;
3.將元素推向Vector的末端
Vector::push_back<E>(v: &mut vector<E>, e: E);
4.獲取對Vector的可變引用,不可變引用可以使用Vector::borrow()
Vector::borrow_mut<E>(v: &mut vector<E>, i: u64): &E;
5.從Vector末端取走一個元素
Vector::pop_back<E>(v: &mut vector<E>): E;
標準庫中的Vector模塊:
