The code excerpts are MREs.
I wrote the following method:
f(a :: T; b :: S = zero(S)) where {T, S} = convert(S, a) + b
It is kinda obvious in hindsight it should not have worked (maybe not even allowed to exist):
> f(1)
ERROR: UndefVarError: S not defined
So I tried to adapt and failed miserably:
> g(a :: T; S = ::Type{T}, b :: S = zero(S)) where {T, S} = convert(S, a) + b
ERROR: syntax: function argument and static parameter names must be distinct
The problem persists if S is not a keyword parameter but a optional positional one:
> h(a :: T, S = ::Type{T}; b = zero(S)) where {T, S} = convert(S, a) + b
ERROR: syntax: function argument and static parameter names must be distinct
And, even if S happens to be a required parameter:
> k(a :: T, S; b :: S = zero(S)) where {T, S} = convert(S, a) + b
ERROR: syntax: function argument and static parameter names must be distinct
But if I conveniently forget to annotate the (obvious and easily inferred) type of b
and remove S
from the where
clause then:
> k(a :: T, S; b = zero(S)) where {T} = convert(S, a) + b
> k(1, Float64)
1.0
> k(1, Float64, b = 2)
3.0
It kinda works, if we do not consider that in an ideal world I would like the method to warn/error me because the argument of b
is not of type S
without needing to write any additional code (clearly, I can write an if
inside the function body for that). The b
parameter is silently promoted.
In my real case, I have three relevant types for the parameters of a method (with many required and keyword parameters), but the third type only appears on the keyword arguments. I wanted the method to assume the third type to be equal to the second type if no keyword/optional argument is given. There is some elegant way to do so?
Seems to me that the hearth of the issue is that Julia prefers to not mix the name of the types inferred from the parameters with the types passed as argument (in truth, with the name of parameters). I am not sure if I like the way Julia works in this very specific point. I think I would prefer if Julia assumed that the required parameter named S
and the S
used in type annotations of other parameters should match (be the same Type), and give me an error if they do not match, but allow me to use a type parameter to define/check the type of many other (specially optional/keyword) parameters. This kind of automatic checking is already kinda made by for “normal” cases where required parameters that share the same parametric type should all match their types.
Also, @Chris_Foster comments on another doubt of mine made me believe there was no relevant distinction between types parameters known-in-compile-time and known-in-run-time, but the error message seems to imply the opposite (by the use of the expression static parameter
). Or this is just a “uh, there is a corner case where the name of a parameter and the type of another parameter are the same, lets just return a error message because the user has probably confounded two distinct things” and then the nomenclature was not the best to make the error message clear.