Canonical way to obtain `NamedTuple` from kwargs

I kept forgetting to ask this. Keyword args are returned as a Pairs iterator. This cannot be converted to a NamedTuple. The simplest way I can see to obtain a NamedTuple from this would be kwargs.data. Presumably this is not, however, a “public” value.

Is there some better way of obtaining the NamedTuple? Thanks in advance!

1 Like
julia> test(;kw_args...) = values(kw_args)
julia> test(a = 22) |> typeof
NamedTuple{(:a,),Tuple{Int64}}
9 Likes

Nice, thanks. This probably should get documentation somewhere here, hopefully I’ll remember to make a PR…

1 Like

I wonder, why kwargs is not a NamedTuple, any insights?

1 Like

So you can iterate symbol => value.

2 Likes

Conversely, is there a canonical way to splat a named tuple as keyword arguments?

As far as I know this is just, for example

f(;n...)
1 Like

No, that splats as positional arguments.

ulia> k = (a = 1, b = 2)
(a = 1, b = 2)

julia> f(x, y) = [x, y]
f (generic function with 1 method)

julia> g(;x=0, y=0) = [x, y]
g (generic function with 1 method)

julia> f(k...)
2-element Array{Int64,1}:
 1
 2

julia> g(k...)
ERROR: MethodError: no method matching g(::Int64, ::Int64)
Stacktrace:
 [1] top-level scope at none:0

You’re missing a semi-colon ;.

2 Likes

Ah, right, thanks.

If you ever get to that PR, please include this direction too, even if it is obvious when you’re awake enough.

1 Like

How come they don’t execute with the same speed? (unrelated)

julia> using BenchmarkTools
julia>  f(x,y) = x+y*x
f (generic function with 1 method)

julia>  g(;x, y) = x+y*x
g (generic function with 1 method)

julia>  k = (x=2,y=32)
(x = 2, y = 32)

julia> @btime f(k...)
  114.007 ns (1 allocation: 112 bytes)
66

julia> @btime g(;k...)
  64.446 ns (1 allocation: 32 bytes)
66

julia> @btime f($k...)
  120.523 ns (2 allocations: 144 bytes)
66

julia> @btime g(;$k...)
  1.899 ns (0 allocations: 0 bytes)
66
1 Like

Is because k is a global variable.

Tuples have special handling for splatting in the compiler which doesn’t currently seem to extend to NamedTuples

julia> kk = (2, 32)
(2, 32)

julia> @btime f($kk...)
  0.025 ns (0 allocations: 0 bytes)
66
2 Likes

doh yeah,

julia> const k = (x=2,y=32)
(x = 2, y = 32)

julia> f(x,y) = x+y*x
f (generic function with 1 method)

julia>  g(;x, y) = x+y*x
g (generic function with 1 method)

julia> @btime f(k...)
  140.377 ns (1 allocation: 112 bytes)
66

julia> @btime g(;k...)
  2.399 ns (0 allocations: 0 bytes)
66

julia> @btime f($k...)
  158.462 ns (2 allocations: 144 bytes)
66

julia> @btime g(;$k...)
  2.599 ns (0 allocations: 0 bytes)
66

Tuples have special handling for splatting in the compiler which doesn’t currently seem to extend to NamedTuples

is there an open issue for that?

I guess NamedTuple could be added to Performance of splatting a number · Issue #29114 · JuliaLang/julia · GitHub.

2 Likes