Nested loop confusion

The two cases have similar syntax, but different semantics. Consider the following versions of your examples:

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

and

julia> for i=1:2, j=i:4
       @show i,j
       end
(i, j) = (1, 1)
(i, j) = (1, 2)
(i, j) = (1, 3)
(i, j) = (1, 4)
(i, j) = (2, 2)
(i, j) = (2, 3)
(i, j) = (2, 4)

In the for case, the faster moving index is the second, and in the comprehension it is the first. The example of the for loop also shows why this is so: to enable the second index to depend on the value of the first index. In essence, the for loop is syntactic sugar for a double nested for, and as such maintains the order of the index ranges:

for i=1:2
  for j=i:4
    ||
    \/
for i=1:2, j=i:4

In the comprehension, the ranges are in the array indexing order. With the fastest index being the first. Indeed, the comprehension returns an array.
This logic may also help remember this confusing bit.
Hope this helps (this answer not written by GPT-3, maybe GPT-5 :wink: )

4 Likes