Yep, an equivalent result to falses(L)
can be done by removing the macro call:
julia> let L = 5, Q = [false for i in 1:L]
@show L, Q
end
(L, Q) = (5, Bool[0, 0, 0, 0, 0])
(5, Bool[0, 0, 0, 0, 0])
This is what the MVector
macro does:
macro MVector(ex)
static_vector_gen(MVector, ex, __module__)
end
And this is what static_vector_gen
does to :comprehension
expressions like the example:
elseif head === :comprehension
#= omitted some input validation =#
ex = ex.args[1]
#= omitted some input validation =#
rng = Core.eval(mod, ex.args[2].args[2])
exprs = (:(f($j)) for j in rng)
return quote
let
f($(esc(ex.args[2].args[1]))) = $(esc(ex.args[1]))
$SV{$(length(rng))}($tuple($(exprs...)))
end
end
rng = Core.eval(mod, ex.args[2].args[2])
evaluates 1:L
in the global scope because it needs a preexisting value while still parsing the let
expression to put a number of arguments into the tuple call jling showed. This also causes problems if the global value would be instantiated too late, like if this were a begin
block defining L
before a @MVector
call. This is documented behavior, per the docstring for @SArray
:
2. comprehensions
│ Note
│
│ The range of a comprehension is evaluated at global scope by the macro, and must be made of
│ combinations of literal values, functions, or global variables.
The most direct Github issue for local variables in comprehension ranges is #26, but it was closed in favor of the wider #97. The workaround given there is to skip the macro:
julia> let L = 5, Q = MVector{L}(false for i in 1:L)
@show L, Q
end
(L, Q) = (5, Bool[0, 0, 0, 0, 0])
(5, Bool[0, 0, 0, 0, 0])