How to achieve type stability when assigning values with StaticArrays?

Viewed 52

I have the following struct (simplified), and some calculations done with this struct:

mutable struct XX{VecType}
 v::VecType
end

long_calculation(x::XX) = sum(x.v)

as a part of the program i need to update the v value. the struct is callable and mainly used as a cache. here, the use of static arrays helps a lot in speeding up calculations, but the type of v is ultimately defined by an user. my problem lies when assigning new values to XX.v:

function (f::XX)(w)
  f.v .= w #here lies the problem
  return long_calculation(f)

this works if v <: Array and w is of any value, but it doesn't work when v <: StaticArrays.StaticArray, as setindex! is not defined on that type.

How can i write f.v .= w in a way that, when v allows it, performs an inplace modification, but when not, just creates a new value, and stores it in the XX struct?

2 Answers

There's a package for exactly this use case: BangBang.jl. From there, you can use setindex!!:

f.v = setindex!!(f.v, w)

Here I propose a simple solution that should be enough in most cases. Use multiple dispatch and define the following function:

my_assign!(f::XX, w) = (f.v .= w)
my_assign!(f::XX{<:StaticArray}, w) = (f.v = w)

and then simply call it in your code like this:

function (f::XX)(w)
    my_assign!(f, w)
    return long_calculation(f)
end

Then if you (or your users) get an error with a default implementation it is easy enough to add another method to my_assign! co cover other special cases when it throws an error.

Would such a solution be enough for you?

Related