2 个不稳定版本
0.2.0 | 2020年5月9日 |
---|---|
0.1.0 | 2020年5月8日 |
#1984 in Rust 模式
每月 270 次下载
16KB
153 行
array-lit
Rust 宏,用于具有超能力的数组和 Vec
文字字面量。数组的宏名为 arr!
;Vec
的宏名为 vec!
,它会覆盖标准库中的宏。
它们允许创建一个数组或 Vec
,其中只指定了一些元素,其余设置为默认值。
以下宏指定了索引 0 上的三个连续值
let a = arr![0; 8; { [0]: [1, 2, 3] }];
assert_eq!(a, [1, 2, 3, 0, 0, 0, 0, 0]);
只有指定多个连续元素时才需要方括号
let a = arr![1; 8; { 6: 0 }];
assert_eq!(a, [1, 1, 1, 1, 1, 1, 0, 1]);
您可以根据需要指定任意数量的单个和连续值
let a = arr![0; 8; {
6: 1, // 1 at index 6
[2]: [3, 4], // 3 and 4 starting from index 2
7: 5, // 5 at index 7
}];
assert_eq!(a, [0, 0, 3, 4, 0, 0, 1, 5]);
支持熟悉的数组语法(arr![a; N]
和 arr![a, b, c]
),因此此存储库中的 vec!
宏是 std::vec!
的直接替代品。
它是如何工作的?
这些宏生成一个块,首先创建一个数组或 Vec
,然后插入指定的值
arr![4; 10; { 0: 0, 1: 1 }]
// is expanded to
{
let mut arr = [4; 10]; // in the vec! macro, std::vec! is used
arr[0] = 0;
arr[1] = 1;
arr
}
如果插入的数组不是 [a, b, c, ..]
形式,则使用循环
arr![4; 10; { [1]: [2; 4] }]
// is expanded to
{
let mut arr = [4; 10];
let mut i = 1;
let end = i + 4;
while i < end {
arr[i] = 2;
i += 1;
}
arr
}
这甚至适用于在运行时创建的切片、数组和 Vec
let my_slice = &[1, 2, 3, 4];
arr![4; 10; { [1]: my_slice }];
数组的生命周期是什么?
在简单情况下,例如 arr![3; 5]
,数组字面量的生命周期被推断为 'static
。这意味着它们与普通数组字面量的行为完全相同。
在其他情况下,不会推断 'static
生命周期。这意味着数组字面量是在运行时计算的,并且没有固定的内存位置。这也意味着以下
// does NOT compile!
fn return_temporary() -> &'static [i32; 4] {
&arr![0; 4; { 0: 1 }]
}
会产生 error[E0515]: cannot return reference to temporary value
。可以通过首先将字面量赋值给 const
或 static
变量来解决此问题
fn return_temporary() -> &'static [i32; 4] {
static ARR: &[i32; 4] = &arr![0; 4; { 0: 1 }];
ARR
}
分配给 static
或 const
变量的值必须是常量。由于编译器的限制,不允许在宏中展开为循环
// does NOT compile!
const ARR: [i32; 4] = arr![0; 16; { [0]: [1; 8] }];
// this is expanded to a loop ~~~~~~~~~~~^^^^^^
请注意,const
强制执行 const evaluation,这意味着整个数组都被包含在应用程序的二进制文件中。如果数组很大,这可能不是期望的行为。
用法
使用以下命令导入宏
use array_lit::{arr, vec};
如果您不想覆盖 std::vec!
,则可以重命名宏
use array_lit::{arr, vec as vector};
也支持全局导入宏,尽管不推荐这样做
#[macro_use]
extern crate array_lit;
自定义索引
如果您想在这些宏中使用自己的 Index
/IndexMut
实现,您可能需要额外的括号对
#[derive(Copy, Clone)]
struct S(bool);
/// Your custom index
struct Idx(usize);
impl std::ops::Index<Idx> for Vec<S> {
type Output = bool;
// etc.
}
impl std::ops::IndexMut<Idx> for Vec<S> {
// etc.
}
vec![S(true); 1000; { (Idx(16)): false }];
// parens needed ~~~~~^~~~~~~~^
no_std
支持
如果禁用了默认功能,则此库支持 no_std
。这使得 vec!
宏不可用。
最低要求的 Rust 版本
需要 Rust 1.33。
许可证
根据您的选择,许可协议为 MIT 或 Apache 2.0。