【问题标题】:How do I return an array from a Rust function?如何从 Rust 函数返回数组?
【发布时间】:2019-12-03 19:57:54
【问题描述】:

我想创建一个函数,它生成一个大小为 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);
}

【问题讨论】:

    标签: arrays rust


    【解决方案1】:

    我想创建一个函数,它生成一个大小为 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 使用 const generics 使其更符合人体工程学。

    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);
    }
    

    如果您在编译时不知道长度,或者它太大而无法放入堆栈,那么您可以使用的最接近数组的是Box&lt;[T]&gt;Box 的切片 Tinto_boxed_slice().

    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 中不存在数组的概念,因此这是一个非推论。
    【解决方案2】:

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

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

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

    【讨论】:

    • 什么语言的数组可以增长或缩小?
    • 我对其他语言了解不多,但 Python 有一个称为“列表”的数组,它可以增长和缩小。
    • 所以不是数组,列表是列表而不是数组
    • 是的 javascript 是...好吧,实际上,当您在 javascript 中的数组上推送某些内容时,您会创建一个新数组,在 javascript 中一切都是 const,无论如何您明白我的意思,数组通常意味着“固定大小“因为 50 年以来的情况如何,这就是为什么许多其他语言使用向量、列表等名称来表示连续元素。此外,这在像 C 这样的语言中非常重要,其中数组非常精确,很多人仍然错误地使用数组这个词。所以我会说“像 Rust 中的其他编程语言一样,数组不能增长或缩小”:p
    • 问:“什么语言的数组可以增长或缩小?”答:蟒蛇:docs.python.org/2.7/library/array.html
    【解决方案3】:

    调整你的函数,并且仍然返回一个数组,需要指定返回类型中的元素数量,即fn generateArray()-&gt;[f64; 100]。 rust 类型系统考虑了数组的大小,因此[f64; 100](包含f64s 的长度为100 的数组)是与[f64; 99] 不同的类型。在函数中指定数组的长度会降低重用性,因为它总是返回相同大小的数组。

    如果您只是必须创建充满随机浮点数的堆栈分配数组,则可以使用宏,但这会将您限制为在编译时已知的数组大小(C++ 术语中的constexpr,Rust 术语中的const)。我认为这种宏观方法有点生锈。宏可能看起来像

    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);
    }
    

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

    【讨论】:

      猜你喜欢
      • 2017-04-07
      • 2011-05-14
      • 2022-10-01
      • 2019-12-28
      • 1970-01-01
      • 2020-07-07
      相关资源
      最近更新 更多