Hacker News new | ask | show | jobs
by steveklabnik 1518 days ago
To elaborate, the parent doesn't call get_fizzbuzz_equivalent in a "const context", which would require it to be evaluated at compile time. So it's called at runtime like it didn't have `const`.

You can do something like the nim without build.rs or proc macros:

    #[derive(Debug, Copy, Clone)]
    enum Value {
        Fizz,
        Buzz,
        FizzBuzz,
        Number(usize),
    }
    
    const fn get_fizzbuzz_equivalent<const N: usize>() -> [Value; N] {
        let mut result = [Value::FizzBuzz; N];
    
        let mut i: usize = 0;
        while i < N {
            let n = i + 1;
            if n % 15 == 0 {
                result[i] = Value::FizzBuzz;
            } else if n % 3 == 0 {
                result[i] = Value::Fizz;
            } else if n % 5 == 0 {
                result[i] = Value::Buzz;
            } else {
                result[i] = Value::Number(n);
            };
    
            i += 1;
        }
    
        result
    }
    
    fn main() {
        const FIZZBUZZ: [Value; 31] = get_fizzbuzz_equivalent();
    
        println!("{:?}", FIZZBUZZ);
    }
    
There are certainly some ergonomic issues here; having to use while because for isn't usable in const contexts yet, which is annoying. But this does compute the whole array at compile time.

(Shout-out to https://stackoverflow.com/questions/67538438/const-array-fro... which I basically smashed together with OP's code to produce the above example.)

1 comments

> having to use while because for isn't usable in const contexts yet

For people wondering why, both as Rust outsiders or Rust beginners:

Rust in some sense really only has one loop, just named "loop", which is an infinite loop like while(true) { } in various other languages. Other looping is just syntactic sugar for "loop" specifying some way to escape the loop. Rust's for loop is sugar for a "loop" that uses the IntoIterator trait to get an Iterator and then call next() on it each time the loop repeats, until it breaks out of the loop when next() returns None.

Unfortunately, Iterator::next() isn't a const function. Your actual implementation of next() for trivial data structures probably is constant, but it wants specifically Iterator::next() and that can't be labelled constant today because it's just an implementation of a trait and some other implementations are presumably not constant.

As a result, even though all Rust's loops are just "loop" and "loop" is allowed in a constant function, you can't use the for loop because Iterator::next() is never constant so now your function isn't either.

A proper fix for this would be pretty cool, but is not easy to do.