# Metaprogramming with list comprehensions

**URL:** https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943
**Category:** General Usage
**Tags:** metaprogramming, for-loop, comprehension
**Created:** [June 16, 2025, 9:50pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943 "2025-06-16T21:50:02Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![rokke](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rokke/32/222691_2.png) [@rokke](https://discourse.julialang.org/u/rokke)
#### Post date: [June 16, 2025, 9:50pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/1 "2025-06-16T21:50:03Z")

</div>

I feel like I’m always writing `[foo(a,b,c) for a, b, c in 1:n]` when I mean `[foo(a,b,c) for a in 1:n, b in 1:n, c in 1:n]`, so I’d like to add something to my startup.jl to make it so.

I feel like I’ve seen conflicting information about the ease / feasibility of things like this, so figured before I get too deep I’d ask for resources / suggestions over here

---

<div class="post-metadata">

### Author: ![ForceBru](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/forcebru/32/21389_2.png) [@ForceBru](https://discourse.julialang.org/u/ForceBru)
#### Post date: [June 16, 2025, 9:59pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/2 "2025-06-16T21:59:23Z")

</div>

I think it’s worth learning the difference, actually.

1. `for (a,b,c) in collection` implies that `collection` contains triples that look like `(a,b,c)`.
2. `for a in A, b in B, c in C` are 3 nested loops: first you loop over elements of A, then within this loop you loop over B, then within _that_ loop, loop over C.

This is standard Julia syntax, you’ll find it in the wild and will get confused if you write a macro that modifies its meaning.

---

<div class="post-metadata">

### Author: ![rokke](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rokke/32/222691_2.png) [@rokke](https://discourse.julialang.org/u/rokke)
#### Post date: [June 16, 2025, 10:04pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/3 "2025-06-16T22:04:34Z")

</div>

then is there some other syntax for perfect square/cube/etc matrices? I feel like writing the same thing three times is the wrong way. in your example even you give A B and C as separate objects

---

<div class="post-metadata">

### Author: ![ForceBru](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/forcebru/32/21389_2.png) [@ForceBru](https://discourse.julialang.org/u/ForceBru)
#### Post date: [June 16, 2025, 10:09pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/4 "2025-06-16T22:09:41Z")

</div>

Ah, then you’re probably looking for:

```
for (a, b, c) in Iterators.product(1:n, 1:n, 1:n)

```

This still requires typing `1:n` three times, though.

---

<div class="post-metadata">

### Author: ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)
#### Post date: [June 16, 2025, 10:13pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/5 "2025-06-16T22:13:11Z")

</div>

You can make a small helper function though

```julia
cross(it, n) = Iterators.product((it for _ in 1:n)...)

```

which allows to write `cross(1:n, 3)` instead of `Iterators.product(1:n, 1:n, 1:n)`.  
If it were not type piracy, overloading `(1:n)^3` would also be an option.

---

<div class="post-metadata">

### Author: ![rokke](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rokke/32/222691_2.png) [@rokke](https://discourse.julialang.org/u/rokke)
#### Post date: [June 16, 2025, 11:08pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/6 "2025-06-16T23:08:01Z")

</div>

I spotted that `..` has the same precedence as `:` and left associativity which made me think that `iter..n = cross(iter, n)` would let me `1:n..3`, but it actually results in a parse error. (even with spaces added, so unrelated to `.3`.)

am I misunderstanding something about the precedence table? why does this need parens?  
I tried swapping the order as well in case I just had the wrong direction, but got the same result

using `<|` works l expected it to `[a for a in (1:n)<|(3)]` ; going one level further down to `∷` tries to reach around the whole comprehension `([a for a in 1:n)∷(3])` and going one level up to `++` breaks the range apart `[a for a in 1:(n)++(3)]`, which all makes sense; but `1:n..3` doesn’t seem to be equivalent to either `(1):(n..3)` or `(1:n)..(3)`.

---

<div class="post-metadata">

### Author: ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)
#### Post date: [June 16, 2025, 11:36pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/7 "2025-06-16T23:36:32Z")

</div>

It seems that `..` is not associative at all, contrary to what’s stated in the documentation:

```julia
julia> 1..2..3
ERROR: ParseError:
# Error @ REPL[1]:1:5
1..2..3
# └─┘ ── extra tokens after end of expression

```

In contrast, `:` is associative. It takes three arguments at once, if possible:

```julia
julia> dump(:( 1:2:3:4:5:6 ))
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol :
    2: Expr
      head: Symbol call
      args: Array{Any}((4,))
        1: Symbol :
        2: Expr
          head: Symbol call
          args: Array{Any}((4,))
            1: Symbol :
            2: Int64 1
            3: Int64 2
            4: Int64 3
        3: Int64 4
        4: Int64 5
    3: Int64 6

```

---

<div class="post-metadata">

### Author: ![rokke](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rokke/32/222691_2.png) [@rokke](https://discourse.julialang.org/u/rokke)
#### Post date: [June 16, 2025, 11:38pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/8 "2025-06-16T23:38:40Z")

</div>

so does that mean this is a bug?  
or is there some other reason `..` can’t be associative?

when I did `? ..` I didn’t see anything pop up; is there some common use that prohibits this?

---

<div class="post-metadata">

### Author: ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)
#### Post date: [June 16, 2025, 11:46pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/9 "2025-06-16T23:46:01Z")

</div>

> [@rokke](#):
>
> does that mean this is a bug?

Could be. I hope some expert weighs in.

> [@rokke](#):
>
> when I did `? ..` I didn’t see anything pop up

This is simply because `..` has no asscociated methods in `Base`. If you add a docstring, say with `"docstring for `..`" x..y = x:y`, then it will show up when you say `?..`.

---

<div class="post-metadata">

### Author: ![rokke](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rokke/32/222691_2.png) [@rokke](https://discourse.julialang.org/u/rokke)
#### Post date: [June 16, 2025, 11:48pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/10 "2025-06-16T23:48:22Z")

</div>

> [@matthias314](#):
>
> This is simply because `..` has no asscociated methods in `Base`. If you add a docstring, say with `"docstring for `..`" x..y = x:y`, then will show up when you say `?..`.

a  
yeah, I understood that; I was more saying `it’s not a symbol in any of the packages I currently happen to have open, is it used commonly anywhere else?`

---

<div class="post-metadata">

### Author: ![rokke](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rokke/32/222691_2.png) [@rokke](https://discourse.julialang.org/u/rokke)
#### Post date: [June 16, 2025, 11:53pm UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/11 "2025-06-16T23:53:27Z")

</div>

looks like the other ones at prec-colon all have that same problem  
`… ⁝ ⋮ ⋱ ⋰ ⋯ .… .⁝ .⋮ .⋱ .⋰ .⋯`

looks like maybe it was just forgotten?

> <https://github.com/JuliaLang/julia/blob/a23ce4bcbbb06be413169424cbffee0718b8a431/src/julia-parser.scm#L858>

the range was explicitly defined because it can take 3 arguments, but I don’t see anything for other prec-colon stuff. I think it needs a

```scheme
(define (parse-colon s) (parse-RtoL s parse-expr is-prec-colon?))

```

and for the `parse-expr` on L859, L865, and L880 to be `parse-colon`

idk how it fits into the rest of the codebase but that would at least make it look like the other precedences

should this be brought into a new more appropriately named thread now?

---

<div class="post-metadata">

### Author: ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)
#### Post date: [June 17, 2025, 11:29am UTC](https://discourse.julialang.org/t/metaprogramming-with-list-comprehensions/129943/12 "2025-06-17T11:29:47Z")

</div>

I think you could open an issue on GitHub. For `..` there is a contradiction between the documentation and the implementation. For the other operators there may have never been the intention to support associativity at all. Is there any claim about it in the documentation?

BTW, you are looking at the old flisp parser. My understanding is that Julia is transitioning to JuliaSyntax.jl. You can still get the old parser by setting the environment variable `JULIA_USE_FLISP_PARSER` to `1`. (It has the same problem with `..`.)
