"two-level" futures

I have a futures-based application where I’d like to have two levels: a set of futures that, as each future completes, create an additional set of futures that perform operations based on the result of the “top level” future

My application does async network transactions, but rather than getting bogged down in the details of that, I’ve tried to simplify the problem down and created the following sample program in the Rust Playground.

What it does is: given a set of numbers, multiply each by 2, then, for every result, multiply by 10, 100, and 100. For an initial set of values 1, 2, 3, the result would be:

20
200
2000
40
400
4000
60
600
6000

The application I’m developing uses futures_unordered and a function that creates the futures to be executed. The sample program uses those techniques, but accomplishes only one level. The question is, how do I incorporate the get_times10_future functionality. I understand that there may be a “flattening” operation needed (there is a flatten function for futures). But I’m not quite sure how to work that in.

Did you mean something like this? Or is the 2nd level iterative itself, where you multiply by 10 3 times?

Yes, like that. My get_times10_future was slightly bungled there–it didn’t have a multiplier parameter, but that was the least of my problems.

I wanted the list in the second level to be parameterized, so I modified your example slightly to this.

This is fascinating. My thought was to create a giant set to hand to a single invocation of futures_unordered(). That wasn’t feasible.

Your solution, in summary is.

  1. Create the “multiple by 2” futures and turn it into a FuturesUnordered, which is a stream and thus has iterator-like characteristics.

  2. Chain with and_then, which invokes its closure on every element in the stream as it completes. This creates a Vec of “multiply by 10” futures. Turn this list into a FutureUnordered.

  3. We now have a FutureUnordered, where the elements are themselves FutureUnordereds.

  4. Use flatten to merge the two levels into one larger set of futures.

  5. Call for_each to produce a single future that will invoke a closure for every element.

  6. This “final” future is the value of the lazy function, and will be handed to the Runtime’s block_on function.

This is cool. Let me try this technique out in the “real” program.