It is mostly for type stability. Some types have meaningful numbers in their parameters for example NTuple{N, T}
where N
is the number of elements in the tuple. Letβs say I want to generate 5 3-tuples and perhaps return a Scatter
struct with points field.
julia> struct Scatter{N, T}
points::Vector{NTuple{N, T}}
end
julia> Scatter(N, n) = Scatter([ntuple(i->rand(), N) for i in 1:n])
Scatter
julia> Scatter(::Val{N}, n) where {N} = Scatter([ntuple(i->rand(), N) for i in 1:n])
Scatter
julia> Scatter(3, 5)
Scatter{3,Float64}(Tuple{Float64,Float64,Float64}[(0.599768, 0.863335, 0.0522125), (0.461746, 0.991876, 0.349595), (0.976401, 0.146929, 0.393038), (0.570525, 0.752721, 0.00339558), (0.0793879, 0.612754, 0.00491688)])
julia> @code_warntype Scatter(3, 5)
Body::Scatter{_1,_2} where _2 where _1
1 1 β %1 = %new(getfield(Main, Symbol("##3#5")){Int64}, N)::getfield(Main, Symbol("##3#5")){Int64} β
β %2 = (Base.sle_int)(1, n)::Bool ββ»β·β·β· Colon
β (Base.sub_int)(n, 1) βββ» Type
β %4 = (Base.ifelse)(%2, n, 0)::Int64 ββββ unitrange_last
β %5 = %new(UnitRange{Int64}, 1, %4)::UnitRange{Int64} βββ
β %6 = %new(Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##3#5")){Int64}}, %1, %5)::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##3#5")){Int64}}
β %7 = invoke Base.collect(%6::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##3#5")){Int64}})::Array{_1,1} where _1
β %8 = (Main.Scatter)(%7)::Scatter{_1,_2} where _2 where _1 β
βββ return %8 β
julia> Scatter(Val{3}(), 5)
Scatter{3,Float64}(Tuple{Float64,Float64,Float64}[(0.414659, 0.267734, 0.0170115), (0.763122, 0.858378, 0.45464), (0.0388137, 0.489361, 0.0495321), (0.0409206, 0.00572096, 0.924081), (0.350058, 0.133318, 0.890979)])
julia> @code_warntype Scatter(Val{3}(), 5)
Body::Scatter{3,Float64}
1 1 β %1 = (Base.sle_int)(1, n)::Bool ββ»β·β·β·β· Colon
β (Base.sub_int)(n, 1) βββ» Type
β %3 = (Base.ifelse)(%1, n, 0)::Int64 ββββ unitrange_last
β %4 = %new(UnitRange{Int64}, 1, %3)::UnitRange{Int64} βββ
β %5 = %new(Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##7#9")){3}}, getfield(Main, Symbol("##7#9")){3}(), %4)::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##7#9")){3}}
β %6 = invoke Base.collect(%5::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##7#9")){3}})::Array{Tuple{Float64,Float64,Float64},1}
β %7 = %new(Scatter{3,Float64}, %6)::Scatter{3,Float64} βββ» Type
βββ return %7 β
If this code is in a hot part of the program, this type instability will propagate and slow down your whole program.