What is this for syntax called?

[ i for i in 1:10]

What is this called and how exactly does it work? I get how it’s used (wonderfully convenient), but what is this exactly equivalent to? What and how does it allocate? When should and shouldn’t I use it?

It’s called a list comprehension Single- and multi-dimensional Arrays · The Julia Language

but what is this exactly equivalent to?

It is a syntax for lazy map, filter, and a products over iterators. That is,

If you write

[f(x, y) for x in xs, y in ys if g(x, y)]

then that is equivalent to

itr1 = Iterators.product(xs, ys)
itr2 = Iterators.filter(((x, y),) -> g(x, y), itr1)
itr3 = Iterators.map(((x, y),) -> f(x, y), itr2)
collect(itr3)

allocating an array, usually without any intermediates.

If you instead wrote

(f(x, y) for x in xs, y in ys if g(x, y))

then that would be called a “generator comprehension” and this would not do the final collect stage, just returning an unmaterialized iterator.

5 Likes

The name i normally hear is ‘array comprehension’, since, unlike python’s lists, Julia comprehensions produce arrays.

2 Likes

I just call them list comprehensions (or just ‘comprehensions’), and I think a lot of the community does too, but sure, if you want to be as precise about it as possible, one can call it an array comprehension.

I guess you feel that the word ‘list’ here should always refer to a ‘linked list’, but to be honest I think linked lists are so irrelevant in julia-land that they don’t really deserve to reserve the name ‘list’. As far as I’m concerned, our arrays are lists of items. They’re just not implemented as linked list structures.

1 Like

I mainly meant that I’ve almost only ever heard ‘array comprehension’ on this forum, and whenever someone says ‘list comprehension’ they were corrected. So I assumed the former was the official name.

1 Like

Huh. If that’s the case I never noticed. Either way, ‘array’ would be a more accurate name so good to point out.

Out of curiosity, I searched for the usage of either of those phrases over the last year on this forum… and it turns out they were used the exact same number of times:
28 uses of “array comprehension” vs 28 uses of “list comprehension”

1 Like

I believe ‘array comprehension’ is up by one, actually😉

1 Like

There are other distinctions between “list” and “array” that are probably more relevant: Julia array comprehensions can produce arrays of any dimensionality, and generally try to mimic the axes of the things you iterate over (e.g. offset axes, named axes, block arrays):

julia> using OffsetArrays

julia> X = -1:1;

julia> Y = OffsetArray(reshape(1:6,3,:), 2, -3);

julia> [(x,y) for x in X, y in Y]
3×3×2 OffsetArray(::Array{Tuple{Int64, Int64}, 3}, 1:3, 3:5, -2:-1) with eltype Tuple{Int64, Int64} with indices 1:3×3:5×-2:-1:
[:, :, -2] =
 (-1, 1)  (-1, 2)  (-1, 3)
 (0, 1)   (0, 2)   (0, 3)
 (1, 1)   (1, 2)   (1, 3)

[:, :, -1] =
 (-1, 4)  (-1, 5)  (-1, 6)
 (0, 4)   (0, 5)   (0, 6)
 (1, 4)   (1, 5)   (1, 6)
1 Like

(Neither are Python lists, which are simply arrays of object pointers internally, exactly like Vector{Any} in Julia.)

1 Like