I am using a parametric structure parameterized by an integer parameter p.
Depending on the value of p, the function f will have different behaviors.
What is the best solution: write an if elseif else structure inside the function f or dispatch f according to the value of p.
If I choose this second option, how should I write the dispatch? I have something like this in mind but this is not the right syntax.
struct mystruct{p}
A::Array{Float64,2}
end
f(m::mystruct{p}) where {p==0}
# do operations
end
f(m::mystruct{p}) where {p>0}
# do different operations
end
I just give this configuration with one parameter as a toy problem. In reality, I have 3 parameters to parameterize my structure.
Instead of making a long function with all the different possible combinations, I ‘ve thought that creating a function dispatched according to these cases will be more efficient than nested if conditions.
It’s not really about efficiency, but about convenience. You can write it whichever way you want, just do it whichever way you think is nicer and gives cleaner, more readable code.
If methods for different parameters share a lot of code, maybe it’s easier to write them in a single function body. If not, it may be better to write different methods.
You can do it like this (note that typenames should be CamelCase, not lowercase):
function f(m::MyStruct{0}) # method 1
# do operations
end
function f(m::MyStruct{p}) where {p} # method 2
# do operations
end
You cannot do arithmetic or comparisons such as p > 0 on the type parameter in the function signature, that has to happen inside the function body. Here, p==0 dispatches to method 1, and then every other value for p dispatches to method 2.
Perhaps the most common use is for AbstractArrays:
foo(A::AbstractArray{T,1}) = # definition for vectors
foo(A::AbstractArray{T,2}) = # definition for matrices
Regarding efficiency, because these numbers are known at compile time, the compiler will get rid of all the branches like if p > 0 (leaving only the code for the branch it would’ve taken).
Meaning they should perform identically if you’ve avoided all dynamic dispatches.
Both abstract and concrete types can be parameterized by other types. They can also be parameterized by symbols, by values of any type for which isbits returns true (essentially, things like numbers and bools that are stored like C types or struct s with no pointers to other objects), and also by tuples thereof. Type parameters may be omitted when they do not need to be referenced or restricted.
Yes - I clearly failed to connect some dots here. I thought of array dimensions as a special case, but had not seen a struct parameterized by just a number.
I don’t want to divert the topic from the original question. Thanks for all the responses though.