Rust中是否可以推断数组长度?

24

我可以做到这一点:

let a: [f32; 3] = [0.0, 1.0, 2.0];

为什么这不起作用呢?

let a: [f32; _] = [0.0, 1.0, 2.0];

在我看来,指定长度似乎是冗余且无足轻重的。有没有一种方法可以避免必须显式地指定它?(而且不必将f32附加到所有字面值上。)

4个回答

33

_只能用于两个上下文环境中:在模式(patterns)中,匹配要忽略的值;作为类型(type)的占位符。在数组类型中,长度不是类型(type),而是一个表达式,_不能用于表达式中。

但你可以将f32附加到其中一个字面量(literals)中并完全省略类型(type)。由于数组的所有项必须具有相同的类型,编译器将为该数组推断出正确的元素类型。

let a = [0.0f32, 1.0, 2.0];

9
如果你正在处理常量或静态变量(并且必须指定类型),通常可以使用切片类型代替:static FOO: &[f32] = &[3.0, ...]; - Lukas Kalbertodt
如果您只需要一个切片的不可变引用,那么您可以使用const。但是,如果您需要将切片本身放在静态内存中(即,如果您需要一个&'static &[f32]),则需要另外考虑。 - bluss

7

现在在夜间版本中可以通过 generic_arg_infer 特性实现类型和初始化器的通用参数推断。

#![feature(generic_arg_infer)]

let _arr: [f32; _] = [0.0, 1.0, 2.0];
let _arr: [f32; 3] = [0.0; _];

6
自1.39版本起,可以使用简单的宏实现。
macro_rules! arr {
    ($id: ident $name: ident: [$ty: ty; _] = $value: expr) => {
        $id $name: [$ty; $value.len()] = $value;
    }
}

用法

arr!(static BYTES: [u8; _] = *b"foo");
arr!(let floats: [f32; _] = [0., 1.]);

1
请保留可见性和文档注释的版本:https://gist.github.com/MingweiSamuel/3d6542a8dde4546a19d98b392237514b - Mingwei Samuel
注意,这会对 $value 进行两次评估。 - Chayim Friedman
请注意,这会对$value进行两次评估。 - undefined
@ChayimFriedman 因为这使 $value 成为一个数组类型的长度,所以 $value 必须是 const,而且我认为这意味着我们不必担心多次评估。 - Jack O'Connor

1
如果你正在处理常量或静态变量(必须指定类型),通常使用切片类型:
static FOO: &[f32] = &[0.0, 1.0, 2.0];

这原本是Lukas Kalbertodt对另一个答案的评论。

1
那是一种根本不同的类型。它没有编译时常量长度。 - Timmmm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接