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

查看:131
本文介绍了在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以避免以后出现意外情况.那么,这把我留在哪里呢?我目前可以稳定地做什么,而夜间,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文档有一个放入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] = [\n")?;
  for i in 0..64 {
    write!(f, "  {},\n", ((i as f64).sin().abs() * 2.0_f64.powf(32.0)).floor() as u32)?;
  }
  write!(f, "];\n")?;

  Ok(())
}

然后您可以加载该生成的文件.

then you can load that built file.

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

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