如何从 Rust 函数返回一个数组?

26

我想创建一个函数,生成一个包含随机值的大小为X的数组。

use rand::prelude::*;

fn generateArray(howManyValues: u32)->[f64]
{
    let mut rng = rand::thread_rng();
    let array: [f64, howManyValues];
    for i in 0..howManyValues
    {
        array[i] = rng.gen()*100;
    }

    println!("{:?}", array);
    return array;
}

fn main() {
    generateArray(10);
}
3个回答

32
我想创建一个函数,生成一个随机值为X大小的数组。
类型[f64]是一个slice,而不是一个array。数组需要一个长度,例如[f64; 25]
对于这个任务,Rust的Vec比数组或切片更好,除非您使用某种外部函数接口(FFI),或者Rust API需要一个数组(它可能需要Deref<Target = [T]>,基本上是针对所有类似数组的类型,包括Vec和数组)。Vec类似于C++的std::vector和Java的ArrayList
use rand::prelude::*;

fn generate_vec(len: usize) -> Vec<f64> {
    let mut rng = rand::thread_rng();
    let mut vec = Vec::with_capacity(len);
    for _ in 0..len {
        vec.push(rng.gen::<f64>() * 100.);
    }
    return vec;
}

fn main() {
    let generated_vec = generate_vec(10);
    println!("{:?}", generated_vec);
}

我进行了一些样式更改[1]。如果你真的需要一个数组,请继续阅读。

如果您在编译时知道数组的大小,可以使用数组。如果它太大而无法放入堆栈中,您将会遇到堆栈溢出。Rust 1.51通过常量泛型使这变得稍微更加人性化。

use rand::prelude::*;

fn generate_array<const LEN: usize>() -> [f64; LEN] {
    let mut rng = rand::thread_rng();
    let mut arr = [0.; LEN];
    for item in arr.iter_mut() {
        *item = rng.gen::<f64>() * 100.;
    }
    arr
}

fn main() {
    // generate_array can make an array of any length (within stack size limits)
    let generated_array1:[f64; 5] = generate_array();
    let generated_array2:[f64; 10] = generate_array();
    println!("{:?}", generated_array2);
}

如果您在编译时不知道长度,或者长度太大无法放入堆栈中,则最接近数组的东西是使用into_boxed_slice()Box<[T]>T的切片的Box)。

use rand::prelude::*;

fn generate_array(len: usize) -> Box<[f64]> {
    let mut rng = rand::thread_rng();
    let mut vec = Vec::with_capacity(len);
    for _ in 0..len {
        vec.push(rng.gen::<f64>() * 100.);
    }
    vec.into_boxed_slice()
}

fn main() {
    let generated_array = generate_array(10);
    println!("{:?}", generated_array);
}

[1] 函数名中的单词使用下划线分隔而不是驼峰式,将 println 移动到 main() 中并将 len 的类型更改为 usize,因为这是 Rust 中数组通常索引的方式。


除非您使用某种外部函数接口(FFI),否则在C ABI中不存在数组的概念,因此这是一个不合逻辑的说法。 - Shepmaster

2

首先,与其他编程语言一样,Rust中的数组不能增长或缩小。您可以使用向量。

let v : Vec<i32> = Vec::new();

您可以使用 .push() 函数将值推入向量中。

哪种编程语言有一个可以增长或缩小的数组? - Stargateur
我不太了解其他编程语言,但Python有一种叫做“列表”的数组,可以动态增长和缩小。 - Taimoor
3
所以不是数组,列表就是列表而不是数组。 - Stargateur
1
是的,JavaScript实际上是这样的...当你在JavaScript中将某些东西推入数组时,你会创建一个新数组,在JavaScript中所有都是const,无论如何你明白我的意思,数组通常意味着“固定大小”,因为自50年代以来事情就是这样,这就是为什么很多其他语言使用像向量、列表之类的名称来表示连续元素。此外,在像C这样的语言中,这非常重要,因为数组是非常精确的东西,很多人仍然错误地使用数组这个词。所以我会说“与其他编程语言一样,Rust中的数组不能增长或缩小” :p - Stargateur
1
问:哪种语言有一个可以增长或缩小的数组? 答:Python:https://docs.python.org/2.7/library/array.html - olivecoder
显示剩余3条评论

0
适应您的函数并仍然返回一个数组,需要在返回类型中指定元素数量,即fn generateArray()->[f64; 100]。Rust类型系统考虑了数组的大小,因此[f64; 100](包含f64的长度为100的数组)与[f64; 99]是不同的类型。在函数中指定数组的长度使其可重用性降低,因为它总是返回相同大小的数组。
如果您确实必须创建由随机浮点数填充的堆栈分配的数组,则可以使用宏,但这将限制您在编译时已知的数组大小(C++术语中的constexpr,Rust术语中的const)。我认为这种宏方法略微不符合惯用的Rust风格。该宏可能如下所示:
use rand::prelude::*;

macro_rules! make_array {
    ($size:literal) => {{
        let mut rng = rand::thread_rng();
        let mut arr = [0_f64; $size];
        for item in arr.iter_mut() {
            *item = rng.gen::<f64>()*100.;
        }
        arr
    }}
}

fn main() {
    let arr = make_array!(32);
    println!("{:?}", arr);
    let arr = make_array!(16);
    println!("{:?}", arr);
}

这比修改函数更具可重用性,因为您可以指定不同数量的元素。


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