2

The following Rust code tries to store a closure of zero arguments in an array and call the function.

fn main() { println!("The answer is: {}", solution_fns[0]()); } const solution_fns: [fn() -> isize] = [|| (1..=999).filter(|e| divides(3, e) || divides(5, e)).sum()]; fn divides(d: usize, n: usize) -> bool { n % d == 0 } 

isize] = [|| (1..=999).filter(|e| divides(3, e) || divides(5, e)).sum()];fn divides(d: usize, n: usize) -> bool { n % d == 0}" rel="nofollow noreferrer">Link to Rust playground. Unfortunately it does not compile:

error[E0277]: the size for values of type [fn() -> isize] cannot be known at compilation time --> src/main.rs:5:21 | 5 | const solution_fns: [fn() -> isize] = |
^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait Sized is not implemented for [fn() -> isize]

I understand that you cannot constuct an array (or Vec) of things of which the size is not known at compile-time. However I understand the type [fn() -> isize] to be array of function pointers, and I don't see why a function pointer should not have a known size. Sticking the closure in a Box does not seem to help:

const solution_fns: [Box<fn() -> isize>] = [Box::new(|| { (1..=999).filter(|e| divides(3, e) || divides(5, e)).sum() })]; 

How then can I store an array of closures?

3
  • 1
    The type fn() -> isize has a known size – it's simply a pointer. The problem is that [T] does not have a known size. Try [T; N] with N being the number of closures instead, or use Vec<T> and the vec![] macro. Commented Nov 10, 2021 at 9:23
  • See also this related answer. Commented Nov 10, 2021 at 9:30
  • 1
    Does this answer your question? How to return an array in Rust function Commented Nov 10, 2021 at 10:01

2 Answers 2

4

The problem is not in the fn pointer, but that your array doesnt have a size. It is simply solved by adding the expected size to the array declaration:

const solution_fns: [fn() -> usize; 1] = [|| (1..=999usize).filter(|&e| divides(3, e) || divides(5, e)).sum()]; 

Playground

Sign up to request clarification or add additional context in comments.

4 Comments

I see that I seem to have misinterpreted the error message. Thanks for setting me straight. Is it possible to make the compiler infer the length of the array?
@hkBst Unfortunately, in a static/const, you cannot, only in lets
Apparently you can do this: const SOLVERS: &[fn() -> usize] = &[|| (1..=999).filter(|&e| divides(3, e) || divides(5, e)).sum()];
Better yet, just make up a number N and say the array is [T; N], then the LSP will tell you if N is wrong and it will tell you actual number of elements in the array so you can fix it.
0

If you use a slice, then you don't have to specify the size:

fn main() { println!("The answer is: {}", SOLVERS[0]()); } const SOLVERS : &[fn() -> usize] = &[|| (1..=999).filter(|&e| divides(3, e) || divides(5, e)).sum()]; fn divides(d: usize, n: usize) -> bool { n % d == 0 } 

Link to the playground.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.