I would appreciate it if someone could explain this to me:
x = (somekey=123, someotherkey="test")
y = (someotherkey="test", somekey=123) # same as x but reversed order
h(x::NamedTuple{K,V}) where {K,V} = :somekey in K ? 3 : nothing
@code_warntype h(x)
println()
@code_warntype h(y)
I was expecting all key lookup to happen at compile time since the information is contained in the NamedTuple
type. Instead I obtain:
Body::Int64
1 ─ return 3
Body::Union{Nothing, Int64}
1 ── %1 = $(Expr(:static_parameter, 1))::Core.Compiler.Const((:someotherkey, :somekey), false)
│ %2 = (Base.getfield)(%1, 1, false)::Symbol
└─── goto #12 if not true
2 ┄─ %4 = φ (#1 => %2, #11 => %20)::Symbol
│ %5 = φ (#1 => 2, #11 => %21)::Int64
│ %6 = (%4 === :somekey)::Bool
└─── goto #4 if not %6
3 ── goto #13
4 ── %9 = (Base.sle_int)(1, %5)::Bool
└─── goto #6 if not %9
5 ── %11 = (Base.sle_int)(%5, 2)::Bool
└─── goto #7
6 ── nothing
7 ┄─ %14 = φ (#5 => %11, #6 => false)::Bool
└─── goto #9 if not %14
8 ── %16 = (Base.getfield)(%1, %5, false)::Symbol
│ %17 = (Base.add_int)(%5, 1)::Int64
└─── goto #10
9 ── goto #10
10 ┄ %20 = φ (#8 => %16)::Symbol
│ %21 = φ (#8 => %17)::Int64
│ %22 = φ (#8 => false, #9 => true)::Bool
│ %23 = (Base.not_int)(%22)::Bool
└─── goto #12 if not %23
11 ─ goto #2
12 ┄ goto #13
13 ┄ %27 = φ (#3 => true, #12 => false)::Bool
└─── goto #15 if not %27
14 ─ return 3
15 ─ return Main.nothing
So it works in the first case, when the key I’m checking for is the first in the given named tuple, but it doesn’t in the second.