Array comprehension in a quote

I want to do an array comprehension from a list of ranges in a quote but I get a syntax error.

loops = [:(i=1:2), :(j=1:3)]
:([i+j for :(loops...)]) # ideally maps to [i+j for i=1:2, j=1:3]
syntax: invalid iteration specification

How can I work around this?

This can’t work I think because macros need to have valid Julia syntax at every step and :(for something) is not valid Julia, so :(for $(something)) also does not work.

(You probably meant to use $ inside the quote and not : but this doesn’t change anything)

I don’t really see how to work around this in your case, since I don’t know what problem you are trying to solve. Can you provide more context? Like what do you want to do and why do you think a macro is the solution?

Interpolation indeed does not seem to work.
In any case, you can construct the expression explicitly:


julia> Expr(:comprehension, Expr(:generator, :(i+j), loops...))
:([i + j for i = 1:2, j = 1:3])

julia> eval(ans)
2×3 Matrix{Int64}:
 2  3  4
 3  4  5
2 Likes

The above solution works great though I’m not using it now but I now have a new problem where generated functions apparently don’t work with comprehensions.

My use case it to traverse a complicated nested structure to get some data. Here is the code that creates the quote for the generated function

h = IDSPath("time_slice/:/profiles_2d/0/psi")
function _getindex_gen2(ids, h::Type{IDSPath{H}}) where {H}
    path = _IMAS_HASH_MAP[H]

    I = :(ids.ids)
    I, indices, ranges = _parse_ids_path(I,path)

    if !isempty(indices)
        reverse!(indices)
        reverse!(ranges)
        for (ind, r) in zip(indices,ranges)
            I = :([$I for $ind in $r]) 
        end
    end
    return I
end
_getindex_gen2(x,h) #-->:([((ids.ids.time_slice[i1]).profiles_2d[0]).psi for i1 = 1:length(ids.ids.time_slice)])

My question now is to figure out how to avoid the comprehension entirely but get the same result for the retrieved data i.e. a vector of vectors of vectors… for the data that generally has the same shape but could have different sizes.

For future readers I found a workaround that works. Basically I have to manually create the arrays like so

for (ind,r) in zip(inds,ranges)
    a = Symbol("arr",'_',ind)
    I = quote
        $a = let $a
            $ind,r... = $r
            $a = [$I]
            for $ind in r
                push!($a, $I)
            end
            $a
        end
    end
end

Not sure if there is a better way but this works.