I have a scenario where I’m switching between different methods of one function in a loop that has a long lifetime.
I have a tuple of structs, where I’m selecting one randomly to be put into a function like so:
function somealgo(data, ::Type1)
#do something to data
end
function somealgo(data, ::Type2)
#do something else to data
end
function loop(data::SomeStruct, structs::Tuple, func)
while data.somecondition
selected = rand([1:length(structs);])
somealgo(data, structs[selected})
end
end
This is not so fast due to runtime dispatch. Inlining a switch would be much faster since the lifetime of this loop typically is long and is possible as the ordering, size and types of the structs are always known at compile time. The solution I could think of was using generated functions. What I do here is basically I define all the somealgo
functions to dispatch on ::Type{Type1}
etc. and to then inline what comes down to a switch statement. This is not super elegant and hard to maintain. I’m currently working with string manipulation (which I find a bit more transparent than expressions sometimes), but the code is still hard to read (also the situation in my real code is a bit more complicated, having some more arguments and types to take into account).
I was wondering if there’s some better way to do it. As far as I’m aware you can essentially do a “light” version of a generated function by writing if statements based on static parameters, where the unused branches get compiled away. Is there something similar that you can do for a for loop, which gets unrolled if the necessary details are known during compile time, or something like that?