Handle downstream reduced in a multiplexed complete #33
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes two related bugs I found while trying to write my own transducer with multiplexed reducing functions. Two of the transducers that use
multiplexed
do not correctly handle the potential for a reduced value being returned from the complete of an xform around a multiplexed reducing function when the complete invokes the step of the multiplexed function. Consider the body of the complete for thereduce
transducer:reduce
applies the step ofrf
and then takes care to unwrap any reduced value before passing it to the complete ofrf
. Ifrf
is multiplexed, then its complete is identity, and a reduced value from the step is wrapped in two levels of reduced, resulting in a reduced value being returned from this complete ofreduce
. This is the correct behaviour, butby-key
andmultiplex
do not correctly respect the resulting reduced value.The first resulting bug is just in
multiplex
: if the complete of a multiplexed function returns a reduced value, then the complete will be invoked again. This is because the function that handles invoking all of the reducing functions always completes with the current function if invoking it returns a reduced value, regardless of whether the original invocation was also a completion. The first commit fixes this by adding an extra parameter to indicate if the current invocation is a step or a complete. I've added a test for this bug in the form of the following expression (plus one more for the map case):This currently returns
nil
becauselet-complete
in the complete ofx/reduce
has voided its state, causing it to have no value when it is completed a second time. The first commit includes a test that the result is now2
.The second bug is in both
by-key
andmultiplex
: if the downstream reducing function returns a reduced value in the call to a multiplexed's complete, no more inputs will be processed but all of the remaining multiplexed functions will still be completed when the entire reduction should be stopped and only the original reducing function should be completed. The second commit fixes this by testing if the result of a multiplexed completion is a reduced value after its step returns a reduced value, and destroying any remaining reducing functions in the state if it is. I've added a test for this bug in the form of the following expression (plus two more for the multiplex cases):This currently returns
[:x 3]
because the:y
case bails out of the entire computation when it stops its multiplexed invocation and discovers that the downstream wants to stop too, but then the:x
case is still completed without having processed any more of its inputs. The second commit includes a test that the result is now[:y 4]
.