`Base.accumulate`, but with initial value

Base.accumulate satisfies
length(accumulate(op, input)) == length(input)

I’m looking for a very similar function that satisfies
length(accumulate(op, input; [init])) == length(input) + 1
and
isequal(last(accumulate′\prime(args...;kwargs...)), reduce(args...;kwargs...))

The last property is satisfied for accumulate, except for empty inputs.

A rough implementation would be

accumulate′(args...; kwargs...) = vcat([get(kwargs, :init, :TODO)], accumulate(args...; kwargs...))

Is there a cleaner way to get that behavior with existing primitives? It would be cool if there were some composable way to get this behavior, so that e.g. last(cumsum′(Int[])) == sum(Int[])

Here is a way to do this with Transducers.jl:

using Transducers
accumulate′(op, xs; init) = append!!(Scan(op, init), [init], xs)

then

julia> accumulate′(+, []; init = 0)
1-element Array{Int64,1}:
 0

julia> accumulate′(+, [1, 2]; init = 0)
3-element Array{Int64,1}:
 0
 1
 3
1 Like

Thanks! I’ve been meaning to learn about Transducers.jl.

I think it would be great if there were a way to get this behavior without needing to define a helper, and optionally mentioning init just once, using the ontology of InitialValues.jl.

Does something like that fit into the transducers model? Would something like append!!(ScanInit(+, -10), [], [1,2,3]) be possible?

Yeah, you can do this:

ScanInit(op, init) = ScanEmit((acc, x) -> (acc, op(acc, x)), init, identity)

See: https://tkf.github.io/Transducers.jl/dev/manual/#Transducers.ScanEmit

1 Like