# Unexpected (?) behaviour of \`values()\` for generic \`kwargs...\`

**URL:** <https://discourse.julialang.org/t/unexpected-behaviour-of-values-for-generic-kwargs/71938>\
**Category:** General Usage\
**Created:** [November 23, 2021, 11:13am UTC](https://discourse.julialang.org/t/unexpected-behaviour-of-values-for-generic-kwargs/71938 "2021-11-23T11:13:07Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![johnomotani](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnomotani/32/26753_2.png) [@johnomotani](https://discourse.julialang.org/u/johnomotani)\
**Post date:** [November 23, 2021, 11:13am UTC](https://discourse.julialang.org/t/unexpected-behaviour-of-values-for-generic-kwargs/71938/1 "2021-11-23T11:13:07Z")

</div>

If I define a function with `kwargs...`, then I can use `keys()` to get the names of whatever arguments were passed

```julia
julia> function printkeys(; kwargs...)
           println(keys(kwargs))
       end
printkeys (generic function with 1 method)

julia> printkeys(a=1, b=2)
(:a, :b)

```

but if I try and use `values()`, I get a `NamedTuple`

```julia
julia> function printvalues(; kwargs...)
           println(values(kwargs))
       end
printvalues (generic function with 1 method)

julia> printvalues(a=1, b=2)
(a = 1, b = 2)

```

I’d actually have to call `values()` again on the `NamedTuple` to get what I originally expected

```julia
julia> function printvaluesvalues(; kwargs...)
           println(values(values(kwargs)))
       end
printvaluesvalues (generic function with 1 method)

julia> printvaluesvalues(a=1, b=2)
(1, 2)

```

I guess this just says that my expectations were wrong, but if I want a `Tuple` (or possibly `Vector`, or whatever) with just the values of the keyword arguments, is there a more idiomatic way to get it?

---

<div class="post-metadata">

**Author:** ![pfitzseb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pfitzseb/32/45566_2.png) [@pfitzseb](https://discourse.julialang.org/u/pfitzseb)\
**Post date:** [November 23, 2021, 12:56pm UTC](https://discourse.julialang.org/t/unexpected-behaviour-of-values-for-generic-kwargs/71938/2 "2021-11-23T12:56:44Z")

</div>

How about this?

```julia
julia> f(;kwargs...) = Tuple(v for (_, v) in kwargs)
f (generic function with 1 method)

julia> f(a=2, b=3)
(2, 3)

```

---

<div class="post-metadata">

**Author:** ![johnomotani](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnomotani/32/26753_2.png) [@johnomotani](https://discourse.julialang.org/u/johnomotani)\
**Post date:** [November 23, 2021, 11:14pm UTC](https://discourse.julialang.org/t/unexpected-behaviour-of-values-for-generic-kwargs/71938/3 "2021-11-23T23:14:33Z")

</div>

Another possibility that I just stumbled across is

```julia
julia> f(;kwargs...) = Tuple(kwargs.data)
f (generic function with 1 method)

julia> f(a=2,b=3)
(2, 3)

```

Which seems to be able to propagate values that are known at compile-time, in a way that I found useful for generic functions dealing with `NamedDimsArray`s. (Have to confess I haven’t tried @pfitzseb’s method yet).

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [November 24, 2021, 12:41am UTC](https://discourse.julialang.org/t/unexpected-behaviour-of-values-for-generic-kwargs/71938/4 "2021-11-24T00:41:46Z")

</div>

> [@johnomotani](#):
>
> `f(;kwargs...) = Tuple(kwargs.data)`

If you access the `data` field in `kwargs`, then you are relying on the internal implementation details of `Iterators.Pairs`, which could change in any future 1.x version of Julia, so I wouldn’t rely on that approach.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [November 24, 2021, 10:02am UTC](https://discourse.julialang.org/t/unexpected-behaviour-of-values-for-generic-kwargs/71938/5 "2021-11-24T10:02:12Z")

</div>

Just a heads up to OP that this isn’t type-stable, if performance matters.

```julia
julia> f(;kwargs...) = Tuple(v for (_, v) in kwargs)
f (generic function with 1 method)

julia> @code_warntype f(a=2, b=3)
Variables
  #unused#::Core.Const(var"#f##kw"())
  @_2::NamedTuple{(:a, :b), Tuple{Int64, Int64}}
  @_3::Core.Const(f)
  kwargs...::Base.Iterators.Pairs{Symbol, Int64, Tuple{Symbol, Symbol}, NamedTuple{(:a, :b), Tuple{Int64, Int64}}}

Body::Tuple{Vararg{Int64, N} where N}
1 ─ (kwargs... = Base.pairs(@_2))
│ %2 = Main.:(var"#f#1")(kwargs...::Core.PartialStruct(Base.Iterators.Pairs{Symbol, Int64, Tuple{Symbol, Symbol}, NamedTuple{(:a, :b), Tuple{Int64, Int64}}}, Any[NamedTuple{(:a, :b), Tuple{Int64, Int64}}, Core.Const((:a, :b))]), @_3)::Tuple{Vararg{Int64, N} where N}
└── return %2

```

Broadcasting `getindex` seems to be type-stable.

```julia
julia> f(; kw...) = getindex.((kw,), keys(kw))
f (generic function with 1 method)

julia> @code_warntype f(a=2, b=3)
Variables
  #unused#::Core.Const(var"#f##kw"())
  @_2::NamedTuple{(:a, :b), Tuple{Int64, Int64}}
  @_3::Core.Const(f)
  kw...::Base.Iterators.Pairs{Symbol, Int64, Tuple{Symbol, Symbol}, NamedTuple{(:a, :b), Tuple{Int64, Int64}}}

Body::Tuple{Int64, Int64}
1 ─ (kw... = Base.pairs(@_2))
│ %2 = Main.:(var"#f#10")(kw...::Core.PartialStruct(Base.Iterators.Pairs{Symbol, Int64, Tuple{Symbol, Symbol}, NamedTuple{(:a, :b), Tuple{Int64, Int64}}}, Any[NamedTuple{(:a, :b), Tuple{Int64, Int64}}, Core.Const((:a, :b))]), @_3)::Tuple{Int64, Int64}
└── return %2

julia> f(a=2, b=3)
(2, 3)

```
