I am currently writing an API for machine learning algorithms in Rust and I would like for a single genetic algorithm, artificial neural network, or Bayesian network to provide multiple outputs so that for instances in which there may be redundancy, the algorithms can benefit from each other. I intend to use these to produce many outputs, so the amount of outputs is not trivially small.
In C++, if I wanted to return multiple variable outputs, I would likely add them to a vector passed by reference into the function, but that is highly restrictive because it assumes that the user intends for the values to be placed into a vector, and if they need to be moved into any other data structure afterwards, then some overhead will be incurred to copy the resulting outputs.
Since I am using Rust and the trait system is full of many traits that can be implemented for and are implemented for several standard data structures, I am wondering if there is a trait that works like an iterator in that I can call it to add values to any structure in a generic way while also avoiding overhead using Rust's monomorphization.
Alternatively, I am also considering making a FnMut parameter to pass a closure that I can pass these values so they can be consumed however desired. This method is powerful as well, since the values can be consumed directly if they do not need to be placed into a data structure at all. The downside is that I assume, but am not sure, there is the overhead of a function call every time this method is used.
Another way I am considering is using Rust iterators. I think it should be possible to return an iterator from the machine learning algorithm that lazily process parts of the algorithm that are needed to produce each output as each value is requested and then yeild it from the iterator when next() is called on it. I think this method should provide the highest flexibility with the highest performance, but this also seems like it might be an egregious abuse of Rust iterators, although I do see similar things in the standard library. I think it should be possible to implement iterator such that I can store all the intermediary states in computation inside of the iterator struct. This may cause some issues with borrowing from the learning algorithm struct so long as the iterator is in scope though, but I don't think this is a problem.
Which one of these methods is most useful for generic programming and fits in with Rust's best practices? Are there other methods I am not considering that might perform better or provide better support for generic programming? Also, any criticism or advice on how to improve these methods is gladly welcomed and accepted.