问题
I want to compute the factorial of a const
. I want to end up with something like this:
const N: usize = 4;
const N_PERMUTATIONS = factorial(N);
The obvious solutions (that don't work) are:
const fn
– conditional statements are not allowed (or at least not implemented) inconst fn
, neither of the below will compile:const fn factorial(n: usize) -> usize { match n { 0 => 1, _ => n * factorial(n-1) } }
const fn factorial(n: usize) -> usize { if n == 0 { 1 } else { n * factorial(n-1) } }
macros – evaluation of expressions is performed after all macro expansion. This macro will never reach the base case, since after four iterations the argument is
4-1-1-1-1
, which is not matched by0
:macro_rules!factorial { (0) => (1); ($n:expr) => ($n * factorial($n-1)); }
I also tried the following, which would work if *
had short-circuit evaluation, but as-is has unconditional recursion which yields a stack overflow:
const fn factorial(n: usize) -> usize {
((n == 0) as usize) + ((n != 0) as usize) * n * factorial(n-1)
}
(As Matthieu M. pointed out, we can avoid underflow by using factorial(n - ((n != 0) as usize))
.)
For now I've resorted to manually computing the factorial.
回答1:
This is currently explored under the feature const_fn
, but for now you cannot call a function, even const, from another const function.
You can however break out the big guns: metaprogramming (procedural macro) to compute the value at compile-time. I found this crate for example (but did not test it, though).
This Rosetta Code page on compile time calculation shows that the compiler can do some compile-time optimization, but nothing is guaranteed, and this is only a particular case.
来源:https://stackoverflow.com/questions/44448488/is-it-possible-to-have-a-recursive-function-computed-at-compile-time-in-rust