# Consistency between \`keys\`, \`values\`, and \`getindex\` for \`Pair\` type

**URL:** <https://discourse.julialang.org/t/consistency-between-keys-values-and-getindex-for-pair-type/83088>\
**Category:** Internals & Design\
**Created:** [June 20, 2022, 7:04pm UTC](https://discourse.julialang.org/t/consistency-between-keys-values-and-getindex-for-pair-type/83088 "2022-06-20T19:04:13Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![goretkin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goretkin/32/167_2.png) [@goretkin](https://discourse.julialang.org/u/goretkin)\
**Post date:** [June 20, 2022, 7:04pm UTC](https://discourse.julialang.org/t/consistency-between-keys-values-and-getindex-for-pair-type/83088/1 "2022-06-20T19:04:13Z")

</div>

Consider

```julia
julia> nt = (;a = 10, b = 20)
(a = 10, b = 20)

julia> [(;k, v) for (k, v) in pairs(nt)]
2-element Vector{NamedTuple{(:k, :v), Tuple{Symbol, Int64}}}:
 (k = :a, v = 10)
 (k = :b, v = 20)

```

The above suggests that the keys of `nt` are `Symbol`s. The values of `nt` are `Int`s. Indeed,

```julia
julia> keys(nt)
(:a, :b)

julia> values(nt)
(10, 20)

```

When a collection is `getindex`ed with value in the key space, it produces a value in the value space:

```julia
julia> nt[:a]
10

```

So far so good.

I do not see such consistency within the `Pair` type itself.

```julia
julia> p = pairs(nt)
pairs(::NamedTuple) with 2 entries:
  :a => 10
  :b => 20

julia> [(;k, v) for (k, v) in pairs(p)]
2-element Vector{NamedTuple{(:k, :v), Tuple{Symbol, Int64}}}:
 (k = :a, v = 10)
 (k = :b, v = 20)

```

This suggests that the key space is `Symbol` and the value space is `Int`. However,

```julia
julia> keys(p)
(:a, :b)

julia> values(p) # hmm?
(a = 10, b = 20)

julia> p[:a]
10

```

~~Does the TODO in the [definition of `values(::Pairs)`](https://github.com/JuliaLang/julia/blob/7a1e40/base/iterators.jl#L289) refers to this issue?~~

---

<div class="post-metadata">

**Author:** ![goretkin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goretkin/32/167_2.png) [@goretkin](https://discourse.julialang.org/u/goretkin)\
**Post date:** [June 20, 2022, 7:25pm UTC](https://discourse.julialang.org/t/consistency-between-keys-values-and-getindex-for-pair-type/83088/2 "2022-06-20T19:25:39Z")

</div>

I was trying to express an invariant that I expected to be violated:

```julia
julia> function check_invariant(collection)
         for k in keys(collection)
           collection[k] in values(collection) || return false
         end
         return true
       end
check_invariant (generic function with 1 method)

```

And thankfully,

```julia
julia> check_invariant(nt)
true

julia> check_invariant(pairs(nt))
true

```

I was confused because `values(pairs(nt))` happens to include some keys (as helpfully pointed out by @ericphanson on Slack), but I see now why there is no inconsistency, because of the way that `values(pairs(nt))` iterates.

I was updating some Julia code to not use `kwargs.data` to access the `NamedTuple` underlying splatted kwargs, and using `values` looked wrong, because it looked like `value(kwargs)` would not contain any key data (since `values(::NamedTuple)` does not either). This confused me.
