Is the first key of a NamedTuple special?

#1

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.

#2
2 Likes
#3

Thanks!

#4

Also see Base.sym_in for an implementation that works around this.

1 Like