# How do I retrieve values using an array generator?

**URL:** https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421
**Category:** New to Julia
**Tags:** array, generator, iterators
**Created:** [October 26, 2023, 6:18am UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421 "2023-10-26T06:18:09Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![crustaccione](https://avatars.discourse-cdn.com/v4/letter/c/59ef9b/32.png) [@crustaccione](https://discourse.julialang.org/u/crustaccione)
#### Post date: [October 26, 2023, 6:18am UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/1 "2023-10-26T06:18:09Z")

</div>

I know how to create an array using

`array = [x + y for x in 2:8, y in -1:3]`

But I am trying to figure out how to retrieve elements of an array that the array generator creates e.g.

`array_gen = (x + y for x in 2:8, y in -1:3)`

How do I extract the values I need e.g. if I just want the second row in the array? I know indexing won’t work in this case, do I just use `collect()` and then index it?

---

<div class="post-metadata">

### Author: ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)
#### Post date: [October 26, 2023, 6:24am UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/2 "2023-10-26T06:24:59Z")

</div>

Yes I don’t think there is any other good way. Especially if there is dimensional structure. The generator in principle just produces one value after the next. I don’t think there is any way to just partially manifest it (except sequentially from the start using `first` but that loses the dimensional information) because in principle the generator could have state.

---

<div class="post-metadata">

### Author: ![crustaccione](https://avatars.discourse-cdn.com/v4/letter/c/59ef9b/32.png) [@crustaccione](https://discourse.julialang.org/u/crustaccione)
#### Post date: [October 26, 2023, 6:33am UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/3 "2023-10-26T06:33:20Z")

</div>

I see. So what would be a good use case for array generators, other than what people mention about it saving memory. For example

```julia
array_gen_plus = (x + y for x in 2:8, y in -1:3)
array_gen_mult = (x * y for x in 2:8, y in -1:3)

if True
    collect(array_gen_plus)
else
    collect(array_gen_mult)
end

```

Something like this?

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [October 26, 2023, 7:38am UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/4 "2023-10-26T07:38:04Z")

</div>

> [@crustaccione](#):
>
> So what would be a good use case for array generators

Firstly, it’s called a “generator expression”, and actually it’s often better to consider it as just a bit of syntactic sugar over [`Iterators.map`](https://docs.julialang.org/en/v1/base/iterators/#Base.Iterators.map). Furthermore, there are some user packages that present similar or the same interfaces as `Iterators.map`, but are improved in some respects, e.g.: [`FlexiMaps`](https://juliahub.com/ui/Packages/General/FlexiMaps), [`LazyMapWithElType`](https://juliahub.com/ui/Packages/General/LazyMapWithElType), so you might want to use that instead.

As for what’s a good use case: a generator expression returns an iterator, which are good for iterating over. E.g.: `for el ∈ iterator; ...; end`. Or you can use `mapreduce` or something instead of `for`, of course.

> [@crustaccione](#):
>
> ```julia
> array_gen_plus = (x + y for x in 2:8, y in -1:3)
> array_gen_mult = (x * y for x in 2:8, y in -1:3)
> 
> if True
> collect(array_gen_plus)
> else
> collect(array_gen_mult)
> end
> 
> ```

Not sure if you care, but this code would be nicer after some deduplication. Open a new topic if you’re interested in exploring this.

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [October 26, 2023, 9:58am UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/5 "2023-10-26T09:58:24Z")

</div>

> [@crustaccione](#):
>
> So what would be a good use case for array generators

Generators are nice when you want to _avoid_ collecting, instead just iterating without allocating any temporary array. If you just want to `collect`, then use an array comprehension.

---

<div class="post-metadata">

### Author: ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)
#### Post date: [October 26, 2023, 10:02am UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/6 "2023-10-26T10:02:57Z")

</div>

As DNF said, generators are good when you don’t want to `collect`.

Having said that, if you want to pluck a certain element from the generated Array then you might want to avoid generation of the rest of the elements. This is attempted in the following function:

```julia
generatorgetindex(g, I...) = 
  foldl((x,y)->y,Iterators.take(array_gen,LinearIndices(size(g))[I...]))

```

For example, with `array_gen` from the OP:

```julia
julia> collect(array_gen)
7×5 Matrix{Int64}:
 1 2 3 4 5
 2 3 4 5 6
 3 4 5 6 7
 4 5 6 7 8
 5 6 7 8 9
 6 7 8 9 10
 7 8 9 10 11

julia> generatorgetindex(array_gen, 2,4)
5

```

---

<div class="post-metadata">

### Author: ![crustaccione](https://avatars.discourse-cdn.com/v4/letter/c/59ef9b/32.png) [@crustaccione](https://discourse.julialang.org/u/crustaccione)
#### Post date: [October 26, 2023, 3:14pm UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/7 "2023-10-26T15:14:22Z")

</div>

Thank you! This is exactly what I was thinking about, but it seems like there isn’t a function to do this natively?

---

<div class="post-metadata">

### Author: ![crustaccione](https://avatars.discourse-cdn.com/v4/letter/c/59ef9b/32.png) [@crustaccione](https://discourse.julialang.org/u/crustaccione)
#### Post date: [October 26, 2023, 3:16pm UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/8 "2023-10-26T15:16:31Z")

</div>

Maybe I just haven’t come across a good use case for what I’ve been doing so far, but I can’t figure out when I would need to iterate without collecting. Unless say I have several possible iterated arrays of huge dimensions that I don’t want to allocate at the start?

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [October 26, 2023, 3:20pm UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/9 "2023-10-26T15:20:05Z")

</div>

> [@crustaccione](#):
>
> but I can’t figure out when I would need to iterate without collecting.

A classic application is if you want to find the sum or maximum over something:

```julia
sum(tan(x)^2 for x in X) 

```

is more efficient than

```julia
sum([tan(x)^2 for x in X]) 

```

or

```julia
sum(tan.(X).^2) 

```

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [October 26, 2023, 3:36pm UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/10 "2023-10-26T15:36:59Z")

</div>

My favorite is usually `mapreduce((x -> x^2) ∘ tan, +, X, init = zero(eltype(X)))`.

`mapreduce` should be better than composing iterators several levels deep, at least with the current iteration protocol.

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [October 26, 2023, 3:43pm UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/11 "2023-10-26T15:43:12Z")

</div>

One thing I really like about the generator sum is that I don’t have to mess about to find the correct initial value type.

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [October 26, 2023, 3:45pm UTC](https://discourse.julialang.org/t/how-do-i-retrieve-values-using-an-array-generator/105421/12 "2023-10-26T15:45:02Z")

</div>

`sum` isn’t different than `mapreduce` in this regard, it seems:

```julia-repl
julia> sum(Int[])
0

julia> reduce(+, Int[])
0

julia> mapreduce(identity, +, Int[])
0

```

EDIT: no, you’re right. The above result is because `identity` is special-cased, I guess.

Still, even `sum` will fail when it can’t infer a good type, e.g., `sum([])` fails. Or it could return an inappropriate type, if the element type of the collection its given is abstract.
