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

**URL:** <https://discourse.julialang.org/t/init-for-mutating-op-reduce-op-xs-oninit/123516>\
**Category:** Internals & Design\
**Created:** [December 5, 2024, 9:06pm UTC](https://discourse.julialang.org/t/init-for-mutating-op-reduce-op-xs-oninit/123516 "2024-12-05T21:06:53Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [December 5, 2024, 9:06pm UTC](https://discourse.julialang.org/t/init-for-mutating-op-reduce-op-xs-oninit/123516/1 "2024-12-05T21:06:53Z")

</div>

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)`](https://juliafolds.github.io/Transducers.jl/dev/reference/manual/#Transducers.OnInit) for this, but I don’t know about Base. Do we have a way to do that?

* * *

cc @mbauman for his work on `reduce`.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [December 5, 2024, 9:25pm UTC](https://discourse.julialang.org/t/init-for-mutating-op-reduce-op-xs-oninit/123516/2 "2024-12-05T21:25:49Z")

</div>

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.

> <https://github.com/JuliaLang/julia/pull/53945#issuecomment-2251018524>
>
> Perhaps more succinctly, just look at \`foldl\`. With \`init\`, it will pass \*all\* i…ts \`itr\` values as right-args. All the left args (except one) are results from previous operations. And \`init\` is that final left-arg. Flip the associativity with \`-r\` and the argument orderings flip. So \`init\`'s placement flips. It makes sense that an arbitrary associativity would grant this leeway.
> 
> If you care about argument orderings between \`init\` and an \`itr\` value, you probably care about the argument orderings between an \`op\` result and an \`itr\` value — and so then you care about the associativity. And you should use \`foldl\` or \`foldr\`.

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`!
