Using julia 0.6.3-pre.2 (built from git), I tried the following:
julia> foo_bar{T<:Union{AbstractString, Symbol}}(d::Union{Symbol, AbstractVector{T}}=AbstractString[]) = "OK"
foo_bar (generic function with 2 methods)
julia> foo_bar()
"OK"
julia> foo_bar([:abc])
"OK"
julia> foo_bar(["abc"])
"OK"
julia> foo_bar(Union{AbstractString, Symbol}["abc", :abc])
"OK"
julia> foo_bar(:abc)
ERROR: MethodError: no method matching foo_bar(::Symbol)
Closest candidates are:
foo_bar(::Union{AbstractArray{T<:Union{AbstractString, Symbol},1}, Symbol}) where T<:Union{AbstractString, Symbol} at REPL[1]:1
foo_bar() at REPL[1]:1
julia>
So my question is why doesn’t Symbol
match Union{AbstractArray{T<:Union{AbstractString, Symbol},1}, Symbol}
?
I’ve also noticed that if I define my function like this:
foo_bar{T<:Union{AbstractString, Symbol}}(d::Union{T, AbstractVector{T}}=AbstractString[]) = "OK"
Then it correctly matches, but then it also matches foo_bar("abc")
I know the best option would be to define different function signatures, but in the code that I’m using, this is a keyword argument, and for backwards compatibility with our legacy code, we need to support the old Symbol
method.
Thanks,
Philip
The problem is that when you pass in just a Symbol argument, the type-variable T
is not defined. Julia v0.6 won’t let you do that, because it requires that all type-variables must have defined values in order for a method to match.
Julia v0.7 removes that requirement, so your example will just work in the future:
julia> foo_bar(d::Union{Symbol, AbstractVector{T}}=AbstractString[]) where {T <: Union{AbstractString, Symbol}} = "OK"
foo_bar (generic function with 2 methods)
julia> foo_bar(:a)
"OK"
(as long as you don’t actually refer to T
inside the body of your function, since T
is still not defined when you pass in a Symbol
).
If you don’t actually need T
at all inside the function, then you can make this work on v0.6 and v0.7 by using the AbstractVector{<:Foo}
construction instead:
julia> foo_bar(d::Union{Symbol, AbstractVector{<:Union{AbstractString, Symbol}}}=AbstractString[]) = "OK"
foo_bar (generic function with 2 methods)
julia> foo_bar(:a)
"OK"
2 Likes
julia> foo_bar(d::Union{Symbol, AbstractVector{<:Union{AbstractString, Symbol}}}=AbstractString[]) = "OK"
foo_bar (generic function with 2 methods)
julia> foo_bar()
"OK"
julia> foo_bar([:abc])
"OK"
julia> foo_bar(["abc"])
"OK"
julia> foo_bar(:abc)
"OK"
Edit: Sniped.
2 Likes
Thanks, makes sense and works, though not in 0.4, and I need to figure that out still (legacy code and all that)