Julia: Mini-julep: use typed Dict key/value types in Pair construction

Created on 18 Aug 2020  ยท  2Comments  ยท  Source: JuliaLang/julia

Currently, the syntax a => b creates the narrowest typed-Pair for a and b. However, when this pair is being used to construct a heterogeneous Dict, this isn't exactly what you want: you'd prefer the pairs to be created from the outset with the Dict's key and value type:

julia> f() = Dict{Symbol,Any}(:a => 1, :b => "hello")
f (generic function with 1 method)

julia> code_typed(f, ())
1-element Vector{Any}:
 CodeInfo(
1 โ”€ %1 = %new(Pair{Symbol,Int64}, :a, 1)::Pair{Symbol,Int64}
โ”‚   %2 = %new(Pair{Symbol,String}, :b, "hello")::Pair{Symbol,String}
โ”‚   %3 = invoke Dict{Symbol,Any}(%1::Pair{Symbol,Int64}, %2::Vararg{Pair,N} where N)::Dict{Symbol,Any}
โ””โ”€โ”€      return %3
) => Dict{Symbol,Any}

julia> @btime f()
  195.619 ns (6 allocations: 672 bytes)
Dict{Symbol,Any} with 2 entries:
  :a => 1
  :b => "hello"

is not as nice (in terms of generated code) as

julia> ft() = Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 1), Pair{Symbol,Any}(:b, "hello"))
ft (generic function with 1 method)

julia> code_typed(ft, ())
1-element Vector{Any}:
 CodeInfo(
1 โ”€ %1 = %new(Pair{Symbol,Any}, :a, 1)::Pair{Symbol,Any}
โ”‚   %2 = %new(Pair{Symbol,Any}, :b, "hello")::Pair{Symbol,Any}
โ”‚   %3 = invoke Dict{Symbol,Any}(%1::Pair{Symbol,Any}, %2::Vararg{Pair{Symbol,Any},N} where N)::Dict{Symbol,Any}
โ””โ”€โ”€      return %3
) => Dict{Symbol,Any}

julia> @btime ft()
  135.983 ns (6 allocations: 672 bytes)
Dict{Symbol,Any} with 2 entries:
  :a => 1
  :b => "hello"

We could have a @Dict that performs this operation, but before implementing this, is there any chance this is something that should just be done by the parser?

Most helpful comment

An alternative might be explicitly converting the pairs in the Dict constructor like this:

julia> struct Dict2{K,V}
           Dict2{K,V}(x::Pair...) where {K,V} = Dict{K,V}(map(p -> convert(Pair{K,V}, p), x)::Tuple{Vararg{Pair{K,V}}}...)
       end

julia> code_typed(f2, ())
1-element Vector{Any}:
 CodeInfo(
1 โ”€ %1 = %new(Pair{Symbol,Any}, :a, 1)::Pair{Symbol,Any}
โ”‚   %2 = %new(Pair{Symbol,Any}, :b, "hello")::Pair{Symbol,Any}
โ”‚   %3 = invoke Dict{Symbol,Any}(%1::Pair{Symbol,Any}, %2::Vararg{Pair{Symbol,Any},N} where N)::Dict{Symbol,Any}
โ””โ”€โ”€      return %3
) => Dict{Symbol,Any}

julia> @btime f()
  216.752 ns (6 allocations: 672 bytes)
Dict{Symbol,Any} with 2 entries:
  :a => 1
  :b => "hello"

julia> @btime ft()
  165.954 ns (6 allocations: 672 bytes)
Dict{Symbol,Any} with 2 entries:
  :a => 1
  :b => "hello"

julia> @btime f2()
  159.693 ns (6 allocations: 672 bytes)
Dict{Symbol,Any} with 2 entries:
  :a => 1
  :b => "hello"

Although I don't know whether that would still be as fast if the pairs are not just constants.

All 2 comments

An alternative might be explicitly converting the pairs in the Dict constructor like this:

julia> struct Dict2{K,V}
           Dict2{K,V}(x::Pair...) where {K,V} = Dict{K,V}(map(p -> convert(Pair{K,V}, p), x)::Tuple{Vararg{Pair{K,V}}}...)
       end

julia> code_typed(f2, ())
1-element Vector{Any}:
 CodeInfo(
1 โ”€ %1 = %new(Pair{Symbol,Any}, :a, 1)::Pair{Symbol,Any}
โ”‚   %2 = %new(Pair{Symbol,Any}, :b, "hello")::Pair{Symbol,Any}
โ”‚   %3 = invoke Dict{Symbol,Any}(%1::Pair{Symbol,Any}, %2::Vararg{Pair{Symbol,Any},N} where N)::Dict{Symbol,Any}
โ””โ”€โ”€      return %3
) => Dict{Symbol,Any}

julia> @btime f()
  216.752 ns (6 allocations: 672 bytes)
Dict{Symbol,Any} with 2 entries:
  :a => 1
  :b => "hello"

julia> @btime ft()
  165.954 ns (6 allocations: 672 bytes)
Dict{Symbol,Any} with 2 entries:
  :a => 1
  :b => "hello"

julia> @btime f2()
  159.693 ns (6 allocations: 672 bytes)
Dict{Symbol,Any} with 2 entries:
  :a => 1
  :b => "hello"

Although I don't know whether that would still be as fast if the pairs are not just constants.

is there any chance this is something that should just be done by the parser

No :smile:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

musm picture musm  ยท  3Comments

omus picture omus  ยท  3Comments

TotalVerb picture TotalVerb  ยท  3Comments

felixrehren picture felixrehren  ยท  3Comments

manor picture manor  ยท  3Comments