在 Rust 中,我可以在不硬编码值的情况下实例化我的 const 数组吗?编译时评估? [英] In Rust, can I instantiate my const array without hard-coding in the values? Compile-time evaluation?

查看:8
本文介绍了在 Rust 中,我可以在不硬编码值的情况下实例化我的 const 数组吗?编译时评估?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 Rust 中实例化一个数组.这是我可以在运行时执行此操作的一种方法:

I'm trying to instantiate an array in Rust. Here's one way I could do it at runtime:

let mut t = [0_u32; 65];
for i in 0..t.len() {
    t[i] = ((i as f64).sin().abs() * 2.0_f64.powf(32.0)).floor() as u32;
}

但是,由于我永远不会更改这个数组的值,而且我会经常使用这些值,所以我认为这可能是一个很好的机会来探索 中的一些很酷的东西const 在 Rust 中完成的编译时评估工作.我可以让它在编译时计算数组并​​将结果存储在程序数据中,以便在运行时立即运行.

However, since I'm never going to change the values of this array and I'm going to use the values a lot, I thought this might be a good opportunity to explore the cool stuff going on with the const compile-time evaluation work being done in Rust. I could make it compute the array at compile time and just store the results in the program data so it's ready to go immediately at runtime.

我的第一步是创建常量数组.

My first step was to create the constant array.

const T: [u32; 65] = [0; 65];

嗯,这不好.我已经用全零实例化了它.那是不对的.接下来,我想也许我应该创建一个可以实例化数组的常量函数.

Well, this is no good. I've already instantiated it with all zeros. That's not right. Next, I thought maybe I should make a constant function that could instantiate the array.

const fn sine_table() -> [u32; 65] {
    let mut t = [0_u32; 65];
    let mut i = 0;


    loop {
        if i > 65 {
            break;
        }

        // Do the math...
    }

    t
}

这就是我卡住的地方.根据我的阅读,常量函数中的循环仍然只在夜间运行,我暂时尝试使用稳定的 Rust,以避免以后出现意外.那么,这将把我留在哪里?我目前可以在稳定状态下做什么,以及在 nightly、RFC 等方面的进展如何?我的下一个想法是研究宏,但我还不够舒服,还不能在不知道它是否会取得成果的情况下进入那个兔子洞.我的最终目标是让这个数组成为一个常量,而不必手动输入 65 个值.

And here's where I got stuck. From what I've read, loops inside constant functions are still only on nightly, and I'm trying to stick with stable Rust for the time being to avoid surprises later on. So, where does this leave me? What can I do currently in stable and what's coming down the pipeline in nightly, RFCs, etc.? My next thought was to investigate macros, but I'm not comfortable enough to go down that rabbit hole just yet without knowing if it'll be fruitful. My ultimate goal is to make this array a constant without having to type in 65 values by hand.

推荐答案

Cargo 支持在整体编译之前编译并运行的 build.rs 文件.对您来说,最简单的选择是使用它来生成您想要使用的表.

Cargo supports build.rs files that are compiled and run before the overall compilation. For you, the easiest option would be to use this to generate the table that you would like to use.

Rust 文档有一个 使用此方法生成代码,因此,如果您使用代码并使用它来生成数组,那么您应该很高兴.您可以将 build = "build.rs" 放入您的 Cargo.toml 并让 build.rs 成为:

The Rust docs have an example for code generation using this method, so if you take your code and use it to generate the array, you should be good to go. You can put build = "build.rs" in your Cargo.toml and have build.rs be:

use std::io::{Result, Write};

fn main() -> Result<()> {
  let out_dir = env::var("OUT_DIR").unwrap();
  let dest_path = Path::new(&out_dir).join("sin_abs_const.rs");
  let mut f = File::create(&dest_path).unwrap();

  write!(f, "const T: [u32; 65] = [
")?;
  for i in 0..64 {
    write!(f, "  {},
", ((i as f64).sin().abs() * 2.0_f64.powf(32.0)).floor() as u32)?;
  }
  write!(f, "];
")?;

  Ok(())
}

然后您可以加载该构建文件.

then you can load that built file.

这篇关于在 Rust 中,我可以在不硬编码值的情况下实例化我的 const 数组吗?编译时评估?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆