Differences between `for i = 1:2, j = 1:3` and `for i = 1:2 for j = 1:3` in comprehensions

Hi guys, I am confused about these two expressions, why are their results different?

julia> [(i, j) for i = 1:2 for j = 1:3]
6-element Array{Tuple{Int64,Int64},1}:
 (1, 1)
 (1, 2)
 (1, 3)
 (2, 1)
 (2, 2)
 (2, 3)

julia> [(i, j) for i = 1:2, j = 1:3]
2×3 Array{Tuple{Int64,Int64},2}:
 (1, 1)  (1, 2)  (1, 3)
 (2, 1)  (2, 2)  (2, 3)

I think the differing behavior is generally useful.

In any case, it seems to be documented:
https://docs.julialang.org/en/stable/manual/arrays/#Comprehensions-1

A = [ F(x,y,...) for x=rx, y=ry, ... ]

...

The result is an N-d dense array with dimensions that are the concatenation of the dimensions of the variable ranges rx, ry, etc.

.
And a bit further down:

Ranges in generators and comprehensions can depend on previous ranges by writing multiple for keywords:

julia> [(i,j) for i=1:3 for j=1:i]
6-element Array{Tuple{Int64,Int64},1}:
 (1, 1)
 (2, 1)
 (2, 2)
 (3, 1)
 (3, 2)
 (3, 3)

In such cases, the result is always 1-d.

.
Note that the latter form allows conditional inclusion of elements in the array, using if keyword.

Generated values can be filtered using the if keyword:

julia> [(i,j) for i=1:3 for j=1:i if i+j == 4]
2-element Array{Tuple{Int64,Int64},1}:
 (2, 2)
 (3, 1)

In this case I think it makes sense to return an unshaped list.

4 Likes