This idea was inspired by the Range literals discussion, where João Bernardo Oliveira suggested this as a use case. However, I think Cartesian product of ranges is of general interest and could be implemented already now with the existing syntaxes.
Sometimes one need to iterate over a grid. This could be a matrix, data table, game map, etc… grids are used in many fields. To iterate over two dimensional grid one can use two nested loops. inside comprehensions, they can be put on a same line
[do_something(x, y) for x in range(width) for y in range(height)]
but outside comprehension, each loop have to be placed on a separate line
for x in range(width): for y in range(height): do_something(x, y)
Iteration over nested grids looks like this
for x in range(width): for y in range(height): # iterate over neighbours for dx in range(-1, 2): for dy in range(-1, 2): do_something(x+dx, y+dy)
Sure, this can handled with defining some separate iterators, but maybe general approach is possible?
@ (which is already used for matrix multiplication) to define the Cartesian product of the ranges, so the previous code is shortened to
[do_something(x, y) for x, y in range(width) @ range(height)] for x, y in range(width) @ range(height): do_something(x, y) for x, y in range(width) @ range(height): # iterate over neighbours for dx, dy in range(-1, 2) @ range(-1, 2): do_something(x+dx, y+dy)
This saves a level of indentation, makes the comprehension and for-loops consistent with comprehensions, makes iteration over three-dimensional grid feasible and four-dimensional grid almost nice (5+ dimensions would require completely different approach anyways).
Generalisation to lists or all iterables?
One can extend this idea to all things iterable, or at least to finite iterables such as lists, dict_keys and sets… I’m not sure about that, as it would have larger consequences. But at least with ranges, I see an immediate use for myself.