I often find myself writing functions where the algorithm implemented depends on the value of an integer. For example, in numerical analysis I often have some numerical method, with 1st, 2nd, 3rd, and 4th order versions of the method each handwritten (because the generalization to each order is not so easy that I can do it programatically). I will have one function wrapper that selects the function with the correct order. E.g.
function wrapper([args], order)
if (order == 1)
return first_order_method([args])
if (order == 2)
return second_order_method([args])
if (order == 3)
return third_order_method([args])
[...]
end
end
If I were writing C++ code, I would do something like
template <int order>
[return type] wrapper([args])
{
if (order == 1)
return first_order_method([args]);
if (order == 2)
return second_order_method([args]);
if (order == 3)
return third_order_method([args]);
}
Using this structure in C++, there would be 3 compiled functions, one for each value of the order. And presumably the compiler would optimize out the if statements for the orders that aren’t used. The julia version, on the other hand, would only have one compiled function (for one set of type in [args]) regardless of the value of args. Whether first_order_method
, second_order_methdo
. etc is called will be determined at runtime.
What is the Julian way of dealing with this? Should I just take the hit and structure my code in such a way that the if statements in a situation like this are inexpensive compared to the function being called in the if statement? Is the compiler able to deal with this in a way I’m not aware of? As I understand it, the more things which are known at compile time the better, which is why I wanted something more along the lines of the C++ version.