# Why does using keys() on an array produce LinearIndices?

**URL:** <https://discourse.julialang.org/t/why-does-using-keys-on-an-array-produce-linearindices/57618>\
**Category:** General Usage\
**Created:** [March 20, 2021, 6:31pm UTC](https://discourse.julialang.org/t/why-does-using-keys-on-an-array-produce-linearindices/57618 "2021-03-20T18:31:28Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![anon60034542](https://avatars.discourse-cdn.com/v4/letter/a/90ced4/32.png) [@anon60034542](https://discourse.julialang.org/u/anon60034542)\
**Post date:** [March 20, 2021, 6:31pm UTC](https://discourse.julialang.org/t/why-does-using-keys-on-an-array-produce-linearindices/57618/1 "2021-03-20T18:31:28Z")

</div>

Suppose I had the following array and used `keys()` to extract the indices:

```julia
trance_singers = String["Emma Hewitt","Carrie skipper","Justine Suissa"]
println(typeof(keys(singers))) # LinearIndices{1,Tuple{Base.OneTo{Int32}}}

```

Why not just a `Int32[]`? I’m guessing, but to ensure that the first array element is in fact 1, it uses `Base.OneTo()`, but why does it need to be inside a `tuple` inside `LinearIndices`?

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [March 20, 2021, 6:42pm UTC](https://discourse.julialang.org/t/why-does-using-keys-on-an-array-produce-linearindices/57618/2 "2021-03-20T18:42:29Z")

</div>

my guess is for memory efficiency, e.g.:

```julia
julia> a=rand(3)
3-element Array{Float64,1}:
 0.8118668996310585
 0.9347418652287747
 0.3923256153519141

julia> sizeof(keys(a))
8

julia> a=rand(1000000000);

julia> sizeof(keys(a))
8

```

In the last case an Int[…] would be of size 8000000000:

```julia
julia> typeof(collect(keys(a)))
Array{Int64,1}

julia> sizeof(collect(keys(a)))
8000000000

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 20, 2021, 8:21pm UTC](https://discourse.julialang.org/t/why-does-using-keys-on-an-array-produce-linearindices/57618/3 "2021-03-20T20:21:11Z")

</div>

> [@anon60034542](#):
>
> but why does it need to be inside a `tuple` inside `LinearIndices` ?

```julia
julia> A = fill(1, (5,6,7));

julia> b = LinearIndices(A);

julia> typeof(b)
LinearIndices{3,Tuple{Base.OneTo{Int64},Base.OneTo{Int64},Base.OneTo{Int64}}}

```

It is inside a Tuple of a single element because it has a single dimension, if it had more dimensions, the tuple would have the same length as the number of dimensions.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [March 21, 2021, 2:22am UTC](https://discourse.julialang.org/t/why-does-using-keys-on-an-array-produce-linearindices/57618/4 "2021-03-21T02:22:54Z")

</div>

> [@anon60034542](#):
>
> Why not just a `Int32[]` ? I’m guessing, but to ensure that the first array element is in fact 1, it uses `Base.OneTo()`

It doesn’t matter what the first index is actually:

```julia
julia> using OffsetArrays

julia> a = rand(5);

julia> keys(OffsetArray(a, -2))
5-element LinearIndices{1,Tuple{OffsetArrays.IdOffsetRange{Int64,Base.OneTo{Int64}}}} with indices -1:3:
 -1
  0
  1
  2
  3

```

> but why does it need to be inside a `tuple` inside `LinearIndices` ?

It needs to be inside a tuple to make as much type information available as possible. The tuple is in the `LinearIndices` so that methods can be written specifically for the `LinearIndices` type (basically to provide “semantics” to the tuple.) `CartesianIndices` has the same underlying tuple but different implementations of (some of) the same functions.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [March 21, 2021, 7:25am UTC](https://discourse.julialang.org/t/why-does-using-keys-on-an-array-produce-linearindices/57618/5 "2021-03-21T07:25:51Z")

</div>

In addition to the answers above: I would just treat the internals of `LinearIndices` as an implementation detail. The main point is that it is an object on which you can `iterate`.

Actually, in this context even `LinearIndices` itself is an implementation detail. It’s just something that `keys` returns.

---

<div class="post-metadata">

**Author:** ![anon60034542](https://avatars.discourse-cdn.com/v4/letter/a/90ced4/32.png) [@anon60034542](https://discourse.julialang.org/u/anon60034542)\
**Post date:** [March 21, 2021, 5:10pm UTC](https://discourse.julialang.org/t/why-does-using-keys-on-an-array-produce-linearindices/57618/6 "2021-03-21T17:10:04Z")

</div>

> [@Tamas\_Papp](#):
>
> In addition to the answers above: I would just treat the internals of `LinearIndices` as an implementation detail. The main point is that it is an object on which you can `iterate` .
> 
> Actually, in this context even `LinearIndices` itself is an implementation detail. It’s just something that `keys` returns.

Seeing as you brought up implementation details, I was wondering if you could clarify something for me. I asked [a question about keyword arguments and how they’re stored](https://discourse.julialang.org/t/is-using-values-the-correct-way-to-obtain-the-namedtuple-in-keyword-arguments/55074), but I wasn’t really satisfied with the answer, so I was hoping to get a second opinion.

When a structure (`NamedTuple`,`LinearIndices`,etc) is considered an implementations detail, is to okay to use that structure?

In the case of keyword arguments, it’s really a `Iterator.Pairs()` holding a `NamedTuple`, and the documentation clearly states it. You can use `values()` to extract the `NameTuple` and access the elements by keywords. However, does relying on it being a `NamedTuple` make the code fragile? I’m assuming if it does change in the future, the documentation would be updated to reflect that, and even if it isn’t, you can call `typeof()` to view the type of structure. Would it be better to create your own `NamedTuple` as demonstrated in the linked answer?

In the context of `LinearIndices`, should I just rely on the fact I have an iterable, rather than a more specific structure?

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [March 22, 2021, 2:03am UTC](https://discourse.julialang.org/t/why-does-using-keys-on-an-array-produce-linearindices/57618/7 "2021-03-22T02:03:32Z")

</div>

Relying specifically on a `NamedTuple` would probably be fragile. Relying on a thing that behaves like a `NamedTuple` is certainly safe. IMO, that is also what the reply to the other thread is demonstrating.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [March 22, 2021, 5:02am UTC](https://discourse.julialang.org/t/why-does-using-keys-on-an-array-produce-linearindices/57618/8 "2021-03-22T05:02:24Z")

</div>

> [@anon60034542](#):
>
> When a structure ( `NamedTuple` , `LinearIndices` ,etc) is considered an implementations detail, is to okay to use that structure?

This depends on how it was created. Eg if you obtained a `LinearIndices` with `keys`, all you can rely on is what `keys` promises (an iterator or collection). However, if you created a `LinearIndices` explicitly, you can assume it is one.

Similarly for `NamedTuple`s, it depends on how you got them. In Julia, APIs are usually organized primarily around _methods_, not _types_.
