I can't understand what's happening here. I reduced the issue to this minimal example:
fn main() {
test(&[f1, f2].to_vec()); // It works when storing different functions
test(&[f1, f1].to_vec()); // <<< It doesn't work when storing only one function
}
fn f1(_x: u8) {}
fn f2(_x: u8) {}
pub fn test(_v: &Vec<fn(u8)>) {}
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:3:10
|
3 | test(&[f1, f1].to_vec()); // <<< It doesn't work when storing only one function
| ^^^^^^^^^^^^^^^^^^ expected fn pointer, found fn item
|
= note: expected reference `&std::vec::Vec<fn(u8)>`
found reference `&std::vec::Vec<fn(u8) {f1}>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
A function item is a special zero-sized type tied to exactly one function in your program. This is useful because it compiles down to just hard-coding the correct function when the function item is used, which is more efficient than calling a dynamic function pointer.
In some cases, the compiler will automatically cast function items to function pointers. You are hitting one of those cases in the first test, but not the latter.
Note that you never want &Vec<T> unless you specifically need to call the capacity() function. Prefer a slice type &[T].
Ok thank you. So in order to have a function that processes a chain of functions, ranging from 1 to n... What would be the rusty thing to do there so it doesn't fail when there is only 1 type of function? Can I cast it to the expected type?
Ok, I converted it to a slice and it seems it solves this particular problem, at least in the example. I'll try it out in the bigger program. Thank you again
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:6:10
|
6 | test(c2); // ERROR: expected slice, found array of 2 elements
| ^^ expected slice, found array of 2 elements
|
= note: expected reference `&[fn(u8)]`
found reference `&[fn(u8) {f1}; 2]`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
Thank you both so much. So obvious in retrospective.I like to see I had three options of which
is my favourite, since I already tried that, but without specifying its size. Unfortunately the compiler error didn't suggested me to do that. EDIT: In the compiler msg was the answer, sorry.
note: expected slice `[fn(u8)]`
found array `[fn(u8); 2]`
I want to end up sharing a more complete example with the addition of type aliases. In this case I found that having extra aliases for the sized Arrays feels the most comfortable.
use ndarray::prelude::*;
pub type A1 = Array1<f64>;
pub type ArrayFunction = fn(&A1) -> A1;
pub type Chain = [ArrayFunction];
pub type Chain1 = [ArrayFunction;1]; // for convenience
pub type Chain2 = [ArrayFunction;2]; // " "
fn main() {
let c1 = [f1, f2]; // OK
test(&c1);
let c2:Chain2 = [f1, f1]; // OK only by specifying the type
test(&c2);
}
fn f1(x: &A1) -> A1 { x.to_owned() }
fn f2(x: &A1) -> A1 { x.to_owned() }
pub fn test(_v: &Chain) {}