# Wrapping methods used by multiple structs

For use running incremental statistics over windowed data, I have some structs that share struct-function-like methods. Here is an example that keeps track of the maximum value encountered as it runs over a windowed data stream.

``````abstract type Accumulator{T} end

mutable struct AccumMax{T} <: Accumulator{T}
max::T
AccumMax(::Type{T}=Float64) where {T} =
(T <: Integer) ? new{T}(typemin(T)) : new{T}(floatmin(T))
end

(accum::AccumMax{T})() where {T} = (accum.max)
(accum::AccumMax{T})(x) where {T} =
(accum.max = ifelse(accum.max < x, T(x), accum.max))
``````
``````julia> accum = AccumMax(Float32)
AccumMax{Float32}(1.1754944f-38)
julia> accum(17.0f0) # the one-arg form accumulates the value
17.0f0
jula> accum(5.0f0);
julia> accum()  # the no-args form retrieves the accumulated value
17.0f0
``````

I want to offer `AccumMaxAbs` that does what `AccumMax` does using `abs(x)` in place of `x`. This is not too hard to do in a way that keeps interoperability with e.g. `AccumMin` so `AccumMinAbs` can be realized the same way.

``````(accum::AccumMax{T})(x, fx::F=identity) where {T,F<:Function} =
(x = fx(x); accum.max = ifelse(accum.max < x, T(x), accum.max))
``````

[currently I recode each explicitly … there are more than two]
It would be great if there were a way to auto-generate the `Abs` versions; I am not concerned so much about making `Abs` versions by hand – I am opaque as to how one approaches modifying the internal calculation in the third statement in a more detailed accumulator. I would like to turn the following into an exponentially weighted version of itself knowing how the modification should be, without entirely recoding it (I would like to offer an exponentially weighted variant of most Accumulators).

``````
mutable struct AccumMeanVariance{T} <: Accumulator{T}
n::Int
mean::T
svar::T
AccumMeanVariance(::Type{T}=Float64) where {T} = new{T}(0, zero(T), zero(T))
end

function (accum::AccumMeanVariance{T})() where {T}
unbiased_var = accum.svar / (accum.n - 1)
(a.mean, unbiased_var)
end

function (accum::AccumMeanVariance{T})(x) where {T}
if !iszero(accum.n)
oldmean = accum.mean
accum.mean = oldmean + (x - oldmean) / accum.n
accum.svar = accum.svar + (x - oldmean) * (x - accum.mean)
else
acccum.mean = x  # svar is zero already
end
end
``````

the exponentially weighted version of this is

``````mutable struct AccumExpWMeanVariance{T} <: Accumulator{T}
n::Int
alpha::T
mean::T
svar::T
AccumExpWMeanVariance(::Type{T}=Float64; alpha::T=0.5) where {T} =
new{T}(0, alpha, zero(T), zero(T))
end

function (accum::AccumExpWMeanVariance{T})() where {T}
unbiased_var = accum.svar / (accum.n = 1)
(accum.mean, unbiased_var)
end

function (accum::AccumExpWMeanVariance{T})(x) where {T}
accum.n += 1
diff = x - accum.mean
incr = accum.alpha * diff
accum.mean += accum.alpha * (x - a.mean)
accum.svar = (one(T) - accum.alpha) * (accum.svar + diff * incr)
end
``````