Open ericniebler opened 10 months ago
Comment by ericniebler Tuesday Oct 25, 2022 at 16:52 GMT
Additional thoughts: the downstream receiver's stop token should be checked at each iteration and the loop terminated if stop has been requested.
For the first algorithmic form, if at any iteration the input sender ends with an error or a stopped signal, the loop should stop executing and that signal propagated immediately.
For the second form, clearly the same behavior makes sense if the predecessor sender fails or is stopped, but what about the loop body (the closure)? Suggestion: if the loop body ends with an error, the loop stops executing and the error is propagated immediately. If the loop body ends with stopped then the loop body stops executing and one of two things happen:
break
, and the cached values should be propagated through the value channel.Since the second algorithmic form can exit the loop early and complete with success, it makes me think the number of times the loop was iterated should be propagated downstream along with the xvalue references to the cached values.
Comment by kirkshoop Wednesday Oct 26, 2022 at 14:48 GMT
It took me a bit to realize that these are defined without sequences and that explains the differences from the rx algorithms.
The first form works with sequences. Later we can add support for the set_next cpo to emit the result of each input sender completion without changing the returned sender from completing with void. With sequences it is a generator.
We will also need a repeat_n for input sequence senders (repeat_all_n?) that repeats the whole sequence and emits all the values in the sequence each time (instead of emitting the result of each input sender completion) as described above.
The second form is different. With sequences, the first form is composed with an index() algorithm to add an index to each set_next emitted and that is composed with then_each or let_each_value to do the closure and that is composed with last() to cache each value in the sequence and emit the cached value when the repeat_all_n completes.
Edited:
The second form would exist because it only starts the input sender once (so it repeats the results, not the side-effects) and because sequences are not in yet.
I am not sure that omitting the side-effects is something that should be combined into repeat. Perhaps the first form can do both.
repeat_n(10, let_value(tag(cache(input)), closure))
@lewissbaker @ericniebler marking as P1 as it's in P3118 (draft).
Issue by ericniebler Tuesday Oct 25, 2022 at 16:28 GMT _Originally opened as https://github.com/brycelelbach/wg21_p2300_execution/issues/4_
These algorithms should come in two forms. Looking at
repeat_n
:repeat_n(loop_count, input_sender)
: sender ofvoid
repeat_n(predecessor_sender, loop_count, sender_adaptor_closure)
: sender of xvalues to values produced by the predecessor senderNumber 2. requires some explanation. It runs the predecessor sender once and caches the values. Then it executes something like
repeat_n(loop_count, just-of-loop-index-and-cached-lvalues | sender_adaptor_closure)
, sending mutable lvalues of the cached values along with the current loop index through the value channel. Afterloop_count
iterations, it sends xvalue references to the cached values to the downstream receiver.Only the second form would support pipe syntax:
predecessor | repeat_n(count, closure)
.