I want to write a method which accepts a closure having a parameter which is an Iterator having some internal implementation. The below implementation of bar achieves this:
Note that the functionality of the inner map is not important here. It is just to illustrate the fact that I have some internal Iterator generated by bar which I want the caller to be able to pass a closure which will operate on that Iterator.
My question: is there any way to replace FnOnce(&mut dyn Iterator<Item = i32>) with a concrete T like FnOnce(Map<...>) which would achieve the same thing without using a trait object? Or is there some other way to achieve this without using a trait object?
Not as-is, because you would have to express that the implementation of bar chooses the type, rather than the caller. So this is either an existential (which a trait object is) or a higher-kinded type with a generic closure (neither of which currently exists in Rust).
What you can do is turn the problem inside out and define your own generic callback trait and type(s). This forces the implementor of the callback trait to accept any type, and then the implementation of bar() can pass in whatever iterator it pleases to:
Perfect, thank you! I guess this means there is no way for a caller to pass an anonymous closure, right? So I'm thinking one approach would be to provide two methods: one which takes a closure, and one a Callback implementation. This way if the user cares enough about performance they can use the Callback version. (I'm from a c# background and I'm just trying to figure out Rust ways of doing things I did in c#).
Interesting... implementing Callback for FnOnce(&mut dyn Iterator) -> i32 worked but required me to annotate the parameter type on the closure, i.e. foo.bar(|values: &mut dyn Iterator<Item = i32>| values.sum()). Makes sense, but also makes it slightly less user-friendly.