# Wrapping methods used by multiple structs

**URL:** <https://discourse.julialang.org/t/wrapping-methods-used-by-multiple-structs/89311>\
**Category:** General Usage\
**Tags:** struct, wrapping-methods\
**Created:** [October 26, 2022, 5:04pm UTC](https://discourse.julialang.org/t/wrapping-methods-used-by-multiple-structs/89311 "2022-10-26T17:04:05Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [October 26, 2022, 5:04pm UTC](https://discourse.julialang.org/t/wrapping-methods-used-by-multiple-structs/89311/1 "2022-10-26T17:04:05Z")

</div>

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.

```julia
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
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.

```julia
(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).

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

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

```
