function countries()
a = JSON.parsefile("country_data.json", dicttype=Dict, use_mmap=true)
c = Vector{String}(undef, length(a))
for (i, d) in enumerate(a)
c[i] = string(d["name"])
end
return c
end
If I replace the length(a)
with a hardcoded value, the function is type stable. I am not sure how it’s not type stable though, length
should always return an integer. And the function is returning an array of Strings. All the types are there…
code_warntype
:
julia> @code_warntype countries()
Body::Any
2 1 ── %1 = JSON.Parser.Int64::Type{Int64} │╻ #parsefile
│ %2 = π (%1, Type{Int64}) ││
│ %3 = (Base.sle_int)(1, 1)::Bool ││╻╷╷╷ isempty
└─── goto #3 if not %3 │││┃││ iterate
2 ── %5 = (Base.sle_int)(1, 0)::Bool ││││┃││ iterate
└─── goto #4 │││││┃ iterate
3 ── nothing │
4 ┄─ %8 = φ (#2 => %5, #3 => false)::Bool ││││││
└─── goto #6 if not %8 ││││││
5 ── invoke Base.getindex(()::Tuple{}, 1::Int64) ││││││
└─── $(Expr(:unreachable)) ││││││
6 ── goto #8 ││││││
7 ── $(Expr(:unreachable)) ││││││
8 ┄─ goto #9 │││││
9 ── goto #10 │││╻ iterate
10 ─ goto #11 │││
11 ─ %17 = π (%2, Type{Int64}) ││
│ %18 = invoke Base.Filesystem.stat("country_data.json"::String)::Base.Filesystem.StatStruct │││╻ filesize
│ %19 = (Base.getfield)(%18, :size)::Int64 ││││╻ filesize
│ %20 = %new(getfield(JSON.Parser, Symbol("##4#5")){UnionAll,DataType,Bool,Int64}, Dict, %17, true, %19)::getfield(JSON.Parser, Symbol("##4#5")){UnionAll,DataType,Bool,Int64} ││╻ #parsefile#3
│ %21 = JSON.Parser.open::typeof(open) │││
│ %22 = invoke Base.:(#open#294)($(QuoteNode(Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}()))::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, %21::Function, %20::getfield(JSON.Parser, Symbol("##4#5")){UnionAll,DataType,Bool,Int64}, "country_data.json"::String)::Any
└─── goto #12 ││
3 12 ─ %24 = (Main.length)(%22)::Any │
│ %25 = (Array{String,1})(Main.undef, %24)::Any │
5 │ %26 = (Main.enumerate)(%22)::Base.Iterators.Enumerate{_1} where _1 │
│ %27 = Base.iterate::Core.Compiler.Const(iterate, false) │
│ %28 = (%27)(%26, (1,))::Union{Nothing, Tuple{Tuple{Int64,Any},Tuple{Int64,Any}}} │╻ iterate
│ %29 = (%28 === nothing)::Bool │
│ %30 = (Base.not_int)(%29)::Bool │
└─── goto #15 if not %30 │
13 ┄ %32 = φ (#12 => %28, #14 => %41)::Union{Nothing, Tuple{Tuple{Int64,Any},Tuple{Int64,Any}}} │
│ %33 = π (%32, Tuple{Tuple{Int64,Any},Tuple{Int64,Any}}) │
│ %34 = (Core.getfield)(%33, 1)::Tuple{Int64,Any} │
│ %35 = (Base.getfield)(%34, 1)::Int64 ││╻ indexed_iterate
│ %36 = (Base.getfield)(%34, 2)::Any │╻ indexed_iterate
│ %37 = (Core.getfield)(%33, 2)::Tuple{Int64,Any} │
6 │ %38 = (Base.getindex)(%36, "name")::Any │
│ %39 = (Main.string)(%38)::Any │
│ (Base.setindex!)(%25, %39, %35) │
│ %41 = (Base.iterate)(%26, %37)::Union{Nothing, Tuple{Tuple{Int64,Any},Tuple{Int64,Any}}} │
│ %42 = (%41 === nothing)::Bool │
│ %43 = (Base.not_int)(%42)::Bool │
└─── goto #15 if not %43 │
14 ─ goto #13 │
8 15 ─ return %25
I think I see what the problem is. The JSON function is not typesafe.
julia> typeof(a)
Array{Any,1}
But I am not really sure how this propagates… length shouldn’t matter.