I feel like this is probably somewhere easily found in the documentation, but I haven’t figured out where, so I think I just don’t know the right vocabulary here.

Suppose I wanted to write the following silly function:

function parsestring(T::Type, s::AbstractString)
v::Union{Nothing,T} = tryparse(T,s)
return v
end
parsestring(Int, "3")
parsestring(Float64, "3.4")

I’ve found the above is slow. Alternatively I could write:

function parsestringFloat64(s::AbstractString)
v::Union{Nothing,Float64} = tryparse(Float64,s)
return v
end
function parsestringInt(s::AbstractString)
v::Union{Nothing,Int} = tryparse(Int,s)
return v
end
parsestringInt("3")
parsestringFloat64("3.4")

which is predictably fast. The question is if there is a more idiomatic way of writing and calling functions in the second case? Do I need to dispatch on values?

I should add that dispatching on values is very fast, although I still feel like I am missing a more idiomatic way to do this:

function parsestring(s::AbstractString, ::Val{T}) where T
v::Union{Nothing,T} = tryparse(T,s)
return v
end
parsestring("3", Val(Int))
parsestring("3.4", Val(Float64))

function parsestring(::Type{T}, s::AbstractString) where {T}
v::Union{Nothing,T} = tryparse(T, s)
return v
end
parsestring(Int, "3")
parsestring(Float64, "3.4")

This is a pattern that shows up fairly often in Julia code.

#general case
function parsestring(::Type{T},s::AbstractString) where T
v::Union{Nothing,T} = tryparse(T,s) #the return is't necessary
end
#optimized case, for int64 and float64
function parsestring(::Type{Int64},s::AbstractString)
v::Union{Nothing,Int64} = tryparse(Int64,s)
end
function parsestring(::Type{Float64},s::AbstractString)
v::Union{Nothing,Float64} = tryparse(Float64,s)
end