Generator questions

While poking around with the generator example below to try understanding the concept, some questions popped up:

  • Why is the last equality false given that the generator was regenerated?
  • With the command g.f(g.iter[n]), are we materializing the nᵗʰ element of the generator?
A = [1 2; 3 4]
B = [A^i for i in 0:2]

g = (A*b for b in B)    # creates generator
G = collect(g)          # 3-element Vector{Matrix{Int64}}
g.f(g.iter[2]) == G[2]  # true
g.f(g.iter[3]) == G[3]  # true

g.iter[3] = ones(2,2)   # assigned to a different matrix here
g.f(g.iter[3]) == G[3]  # false (OK)
g = (A*b for b in B)    # re-creates generator
g.f(g.iter[2]) == G[2]  # true
g.f(g.iter[3]) == G[3]  # false (why does the previous assignment still stand?)

Thank you.

Why is the last equality false given that the generator was regenerated?

As there is no copy for B. The generator g holds the original reference of the iterator here:

julia> objectid(g.iter)
0x35595f9c567dff49

julia> objectid(B)
0x35595f9c567dff49

With the command g.f(g.iter[n]) , are we materializing the nᵗʰ element of the generator?

Only for (... for element in array) it can be true, but in general it is not the case.

There are two counterexamples to your guess.

  1. not all generators use the notion of “nᵗʰ element”:
julia> res = ( [i, j] for i = 1: 2, j = 1:2)
julia> n = 1; res.iter[1]

ERROR: MethodError: no method matching getindex(::Base.Iterators.ProductIterator{Tuple{UnitRange{Int64}, UnitRange{Int64}}}, ::Int64)
  1. we use the iterator interface to handle iterations. Random accessing is not available for iterables.
julia> using DataStructures
julia> xs = list(1, 2, 3)
list(1, 2, 3)

julia> g = (k * 2 for k in xs)
Base.Generator{Cons{Int64}, var"#17#18"}(var"#17#18"(), list(1, 2, 3))

julia> collect(g)
3-element Vector{Int64}:
 2
 4
 6

g.iter[1]
ERROR: MethodError: no method matching getindex(::Cons{Int64}, ::Int64)
2 Likes