KLc3088
KLc3088

Reputation: 97

Why this nested loop generator does not seem to be working?

I was trying this:

tuple(map(tuple, tuple(((x,y) for x in range(5)) for y in range(3))))

I got this:

(((0, 2), (1, 2), (2, 2), (3, 2), (4, 2)),
 ((0, 2), (1, 2), (2, 2), (3, 2), (4, 2)),
 ((0, 2), (1, 2), (2, 2), (3, 2), (4, 2)))

but I expect:

(((0, 0), (1, 0), (2, 0), (3, 0), (4, 0)), 
 ((0, 1), (1, 1), (2, 1), (3, 1), (4, 1)), 
 ((0, 2), (1, 2), (2, 2), (3, 2), (4, 2)))

Upvotes: 2

Views: 66

Answers (2)

KLc3088
KLc3088

Reputation: 97

I used lambda because I think the argument of a function had the property of holding a value.

I do not understand the details of the detailed grammatical evaluation with difficulty, but I was able to successfully prepare a generator that generates a generator by doing the following.

root_gen = ((lambda t: ((t,y) for y in range(3)))(x) for x in range(5))

To evaluate, please use below:

tuple(map(tuple, root_gen)) 

The original idea is as follows:

# generate a sub generator
def sub_gen(x):
    return ((x,y) for y in range(3))

# test 
tuple(gen(1))
tuple(gen(2))

# make generator
root_gen = (gen(n) for n in range(5)) 

# evaluate
tuple(map(tuple(root_gen)))

Upvotes: 0

user2357112
user2357112

Reputation: 281748

You're forcing the evaluations in the wrong order. You're building a generator of generators, building a tuple out of the outer generator to build a tuple of generators, and then building tuples out of the inner generators.

By the time you start working with the inner generators, the outer generator has finished iteration, so y is already 2, the value from the last iteration. This is the y value used the entire time you're iterating over the inner generators, so it's the y value used every time you evaluate (x, y).

You need to call tuple on the inner generators as they're produced, to iterate over them and evaluate (x, y) before y changes:

tuple(tuple((x, y) for x in range(5)) for y in range(3))

Upvotes: 2

Related Questions