1

I am trying to write a function that accumulates numbers provided by a supplier for a given range starting from zero:

fn accumulate<F>(size: usize, supplier: F) -> Successors<f64, fn(&f64) -> Option<f64>>
    where F: Fn(usize) -> f64 {
    let mut range = 0..size;
    successors(
        Some(0.0),
        |acc| range.next().map(|n| *acc + supplier(n)),
    )
}

The error message is:

114 |         |acc| range.next().map(|n| *acc + supplier(&config, n)),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure

This is strange because the successors function expects a closure, namely FnMut. What am I doing wrong?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Albert Gevorgyan
  • 171
  • 3
  • 10
  • This might be useful: https://stackoverflow.com/questions/30177395/when-does-a-closure-implement-fn-fnmut-and-fnonce – bnaecker Nov 04 '20 at 22:18
  • 1
    `fn` is not the same as `Fn`. `Fn` is a callable trait, which closures can conform to. `fn` is a function pointer; closures cannot be converted to function pointers. – C. K. Young Nov 04 '20 at 22:21
  • I understand that a closure cannot be coerced to a function pointer, but I see that the function I am calling actually accepts a closure. Then why does it complain that I am passing in a closure not a function pointer? – Albert Gevorgyan Nov 04 '20 at 22:23
  • 2
    The return type says `fn(&f64)`. – C. K. Young Nov 04 '20 at 22:33
  • 2
    tl;dr the duplicates: use `impl Fn(&f64) -> Option` (or one of the other options described, but `impl Trait` is probably what you want) – trent Nov 05 '20 at 00:25
  • 1
    You probably actually need `FnMut` to allow the closure to mutate its environment, and you might need to add `move` as well. – trent Nov 05 '20 at 00:28

1 Answers1

1

Check the signature for your accumulate function: the return type is Successors<f64, fn(&f64) -> Option<f64>>, i.e., the successor is expecting the second generic parameter to be fn(&f64) -> Option<f64> - a fn.

Try changing that to Fn(&f64) -> Option<f64> - as per the comment from @ChrisJesterYoung.

lxop
  • 7,596
  • 3
  • 27
  • 42
  • Thanks. I have tried to change it to Fn(&f64) -> Option or FnMut(&f64) -> Option but then I am getting this error: "cannot infer type for type parameter `F` declared on the function `accumulate`". – Albert Gevorgyan Nov 04 '20 at 22:52