In Rust, can I instantiate my const array without hard-coding in the values? Compile-time evaluation?

As of now on Rust Stable, this is not possible to do (you need const fn expressions for this to work at compile time).

But fortunately there's an "in-between" solution for this use case (that I have as well quite frequently), which is the lazy_static macro.

Basically it's a lazy-evaluated runtime expression that is computed on first access only.

https://docs.rs/lazy_static/1.4.0/lazy_static/

Your code would look this way using this macro:

use lazy_static::lazy_static;

const SINE_TABLE_SIZE: usize = 65;
lazy_static! {
    pub static ref SINE_TABLE: [u32; SINE_TABLE_SIZE] = {
        let mut table = [0_u32; SINE_TABLE_SIZE];
        for i in 0..SINE_TABLE_SIZE {
            table[i] = ((i as f64).sin().abs() * 2.0f64.powf(32.)).floor() as u32;
        }

        table
    };
}

Rust Playground sample link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=61146c5f7de2c9ee1cbcd724dd1a730f

Disclaimer: I'm not the author of lazy_static nor I am related to them in any way.


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.

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.