Former Matlab user here, still discovering new things about type stability and multiple dispatch…
Currently working on a private package involving mostly linear algebra, I tried to follow the philosophy of julia’s multiple dispatch whenever I could, maybe too much even.
In my package I have a function fun
that has different methods based on some symbol parameter set p1
, p2
, ...
, but always returns the same type. I am not yet used to having types as parameters to perform the multiple dispatch. So my current implementation involves multiple methods defined as
function fun(<common_args...>, ::Val{:p1}`)::ret_type
<some code>
end
function fun(<common_args...>, ::Val{:p2}`)::ret_type
<some other code>
end
And the function calls are done with e.g. : fun(<common_args...>,Val(:p1))
I do not know anymore where I got this trick from, but it works for sure.
However, it seems this can lead to a high stress on the compiler (this comment is based on a discussion on slack)
Also, some @code_warntype
analysis shows that this doesn’t really ensure type stability, even when explicitly specifying the return type for each method in fun
.
In some other way, yet related to the current discussion I tried to see what was done in some base julia code, to see if I could get a typical julia implementation. For instance, take the Hermitian
from Base
.
Hermitian
takes a second argument uplo
which is a symbol (I figured symbols are something important in julia but I can quite fathom how), this comforted me in my practice to use symbols as arguments.
However the definition of Hermitian
is
function Hermitian(A::AbstractMatrix, uplo::Symbol=:U)
n = checksquare(A)
return hermitian_type(typeof(A))(A, char_uplo(uplo))
end
so no check in the value of uplo
is done at that time, just on its type, so there is no multiple dispatch involved here it seems. Then one can see the char_uplo
call… which is actually a check on the value of uplo
! This check is defined as
function char_uplo(uplo::Symbol)
if uplo === :U
return 'U'
elseif uplo === :L
return 'L'
else
throw_uplo()
end
end
The most surprising part of this to me, is that one actually converts the symbol parameter as a char parameter, what is the reasoning behind this ?
Overall my question is: What is the correct way in julia to have a function with multiple implementations differing according to parameter values :
- Is it necessarily through true multiple dispatch where one would define types as parameters e.g.
:p1
would be replaced by ap1type
andfun
would be defined as
function fun(<common_args...>, ::p1type)::ret_type
<some code>
end
function fun(<common_args...>, ::p2type)::ret_type
<some other code>
end
- Is it through type specification with e.g.
p::Symbol
, then applying thechar_uplo
strategy ? - Some other way ?
This has probably been discussed somewhere, but I would really like a feedback on this. As often there will probably be no unique solution, but I just need one…