Init for mutating op: reduce(op!, xs; oninit)

In reduce(append!, lists, oninit=eltype(lists)) we can’t pass init=eltype(lists)() because that value should be append!ed only once. A new init should be generated each time. Transducers.jl provided OnInit(f) for this, but I don’t know about Base. Do we have a way to do that?


cc @mbauman for his work on reduce.

No. We don’t even ensure init is consistently used as you expect here (yet), let alone provide a way to copy it upon each use. We also don’t say which argument slot init goes into.

In short, reduce simply doesn’t have the guarantees necessary to support such mutating ops. I hope some more guarantees will be coming, but even with those I think the argument slot problem will remain.

Even more succinctly, given an iterator x = [a,b], the following should all be allowed to be valid implementations of reduce(f!, x; init):

  • f!(f!(init, a), b)
  • f!(f!(init, a), f!(init, b)) # guaranteeing init is always the left-arg and having a way to init the init would solve this case, yes, but…
  • f!(a, f!(init, b)) # oops, we just mutated an element of x!
1 Like