向量(Vector)
vector<T>
is the only primitive collection type provided by Move. A vector<T>
is a homogenous
collection of T
's that can grow or shrink by pushing/popping values off the "end".
A vector<T>
can be instantiated with any type T
. For example, vector<u64>
, vector<address>
,
vector<0x42::MyModule::MyResource>
, and vector<vector<u8>>
are all valid vector types.
vector<T>
是 Move 提供的唯一原始集合类型。vector<T>
是类型为 T
的同构集合,可以通过从"末端"推入/弹出(出栈/入栈,译者注)值来增长或缩小。
(与 Rust 一样,向量(vector)是一种可以存放任何类型的可变大小的容器,也可称为动态数组,与 Python 中的列表(list)不同,译者注)
vector<T>
可以用任何类型 T
实例化。例如,vector<u64>
、vector<address>
、vector<0x42::MyModuel::MyResource>
和 vector<vector<u8>>
都是有效的向量类型。
字面量(Literals)
通用 vector
字面量(General vector
Literals)
Vectors of any type can be created with vector
literals.
任何类型的向量都可以通过 vector
字面量创建。
语法 | 类型 | 描述 |
---|---|---|
vector[] | vector[]: vector<T> 其中 T 是任何单一的非引用类型 | 一个空向量 |
vector[e1, ..., en] | vector[e1, ..., en]: vector<T> where e_i: T 满足 0 < i <= n and n > 0 | 带有 n 个元素(长度为 n)的向量 |
In these cases, the type of the vector
is inferred, either from the element type or from the
vector's usage. If the type cannot be inferred, or simply for added clarity, the type can be
specified explicitly:
在这些情况下,vector
的类型是从元素类型或从向量的使用上推断出来的。如果无法推断类型或者只是为了更清楚地表示,则可以显式指定类型:
vector<T>[]: vector<T>
vector<T>[e1, ..., en]: vector<T>
向量字面量示例(Example Vector Literals)
(vector[]: vector<bool>);
(vector[0u8, 1u8, 2u8]: vector<u8>);
(vector<u128>[]: vector<u128>);
(vector<address>[@0x42, @0x100]: vector<address>);
vector<u8>
字面量(vector<u8>
literals)
A common use-case for vectors in Move is to represent "byte arrays", which are represented with
vector<u8>
. These values are often used for cryptographic purposes, such as a public key or a hash
result. These values are so common that specific syntax is provided to make the values more
readable, as opposed to having to use vector[]
where each individual u8
value is specified in
numeric form.
There are currently two supported types of vector<u8>
literals, byte strings and hex strings.
Move 中向量的一个常见用例是表示“字节数组”,用 vector<u8>
表示。这些值通常用于加密目的,例如公钥或哈希结果。这些值非常常见,以至于提供了特定的语法以使值更具可读性,而不是必须使用 vector[]
,其中每个单独的 u8
值都以数字形式指定。
目前支持两种类型的 vector<u8>
字面量,字节字符串和十六进制字符串。
字节字符串(Byte Strings)
Byte strings are quoted string literals prefixed by a b
, e.g. b"Hello!\n"
.
These are ASCII encoded strings that allow for escape sequences. Currently, the supported escape sequences are
字节字符串是带引号的字符串字面量,以 b
为前缀,例如,b"Hello!\n"
。
这些是允许转义序列的 ASCII 编码字符串。目前,支持的转义序列如下:
转义序列 | 描述 |
---|---|
\n | 换行 |
\r | 回车 |
\t | 制表符 |
\\ | 反斜杠 |
\0 | Null |
\" | 引号 |
\xHH | 十六进制进制转义,插入十六进制字节序列 HH |
十六进制字符串(Hex Strings)
Hex strings are quoted string literals prefixed by a x
, e.g. x"48656C6C6F210A"
Each byte pair, ranging from 00
to FF
, is interpreted as hex encoded u8
value. So each byte
pair corresponds to a single entry in the resulting vector<u8>
十六进制字符串是以 x
为前缀的带引号的字符串字面量,例如,x"48656C6C6F210A"
。
每个字节对,范围从 00
到 FF
都被解析为十六进制编码的 u8
值。所以每个字节对对应于结果 vector<u8>
的单个条目。
字符串字面量示例(Example String Literals)
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
);
}
}
操作 (Operations)
vector
supports the following operations via the std::vector
module in the Move standard
library:
vector
通过 Move 标准库里的 std::vector
模块支持以下操作:
函数 | 描述 | 中止条件 |
---|---|---|
vector::empty<T>(): vector<T> | 创建一个可以存储 T 类型值的空向量 | 永不中止 |
vector::singleton<T>(t: T): vector<T> | 创建一个包含 t 的大小为 1 的向量 | 永不中止 |
vector::push_back<T>(v: &mut vector<T>, t: T) | 将 t 添加到 v 的尾部 | 永不中止 |
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>) | 将 v2 中的元素添加到 v1 的末尾 | 永不中止 |
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 中第 i 个和第 j 个索引处的元素 | 如果 i 或 j 越界 |
vector::reverse<T>(v: &mut vector<T>) | 反转向量 v 中元素的顺序 | 永不中止 |
vector::index_of<T>(v: &vector<T>, e: &T): (bool, u64) | 如果 e 在索引 i 处的向量中,则返回 (true, i) 。否则返回(false, 0) | 永不中止 |
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 | 将向量中的第 i 个元素与最后一个元素交换,然后弹出该元素。这里的时间复杂度是 O(1),但是不保留向量中的元素顺序 | 如果 i 越界 |
More operations may be added over time.
随着时间的推移可能会增加更多操作。
示例
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
(Destroying and copying vector
)
Some behaviors of vector<T>
depend on the abilities of the element type, T
. For example, vectors
containing elements that do not have drop
cannot be implicitly discarded like v
in the example
above--they must be explicitly destroyed with vector::destroy_empty
.
Note that vector::destroy_empty
will abort at runtime unless vec
contains zero elements:
vector<T>
的某些行为取决于元素类型 T
的能力(ability),例如:如果向量中包含不具有 drop
能力的元素,那么不能像上面例子中的 v
一样隐式丢弃 —— 它们必须用 vector::destroy_empty
显式销毁。
请注意,除非向量 vec
包含零个元素,否则 vector::destroy_empty
将在运行时中止:
fun destroy_any_vector<T>(vec: vector<T>) {
vector::destroy_empty(vec) // 删除此行将导致编译器错误
}
但是删除包含带有 drop
能力的元素的向量不会发生错误:
fun destroy_droppable_vector<T: drop>(vec: vector<T>) {
// 有效!
// 不需要明确地做任何事情来销毁向量
}
Similarly, vectors cannot be copied unless the element type has copy
. In other words, a
vector<T>
has copy
if and only if T
has copy
. However, even copyable vectors are never
implicitly copied:
同样,除非元素类型具有 copy
能力,否则无法复制向量。换句话说,当且仅当 T
具有 copy
能力时,vector<T>
才具有 copy
能力。然而,即使是可复制的向量也永远不会被隐式复制:
换句话说,vector<T>
有 copy
能力当且仅当 T
有 copy
能力。然而,即使是可复制的向量也永远不会被隐式复制:
let x = vector::singleton<u64>(10);
let y = copy x; // 没有 copy 将导致编译器错误!
Copies of large vectors can be expensive, so the compiler requires explicit copy
's to make it
easier to see where they are happening.
For more details see the sections on type abilities and generics.
大向量的复制可能很昂贵,因此编译器需要显式 copy
以便更容易查看它们发生的位置。
所有权(Ownership)
如上所述,vector
值只有在元素值可以复制的时候才能复制。在这种情况下,复制必须通过显式 copy
或者解引用 *
。