Hey,
I was trying to create a function body which contains @nloops N i A
. However, the N
depends on the dimension of the array. Following MWE:
A = randn((2,2,2))
function foo(A::AbstractArray{T, N}) where {T, N}
@nloops N i A begin
println("Do something with the indices")
end
end
foo(A)
However, this throws an error:
ERROR: LoadError: MethodError: no method matching _nloops(::Symbol, ::Symbol, ::Symbol, ::Expr)
Closest candidates are:
_nloops(::Int64, ::Symbol, ::Symbol, ::Expr...) at cartesian.jl:42
_nloops(::Int64, ::Symbol, ::Expr, ::Expr...) at cartesian.jl:47
Stacktrace:
[1] run_repl(::REPL.AbstractREPL, ::Any) at /build/julia/src/julia-1.5.3/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:288
in expression starting at REPL[80]:2
I understand this error if the value of N
would be only available during runtime. However, N
is already determined by type so I would have expected that it could conceptually work.
How can I solve this problem?
Thanks,
Felix
The @nloops
macro only accepts literal integers for N
. Personally, I think it would make sense to just deprecate the @nloops
macro, since there are usually better ways to achieve the same thing. It’s difficult to say what the best solution here would be without a more realistic example, but I would highly recommend reading @tim.holy’s great blog post on multidimensional iteration. CartesianIndices
may well be what you are looking for here.
1 Like
You need to use a @generated function foo
and then interpolate $N
into the returned expression, like the example in the manual.
3 Likes
It seems like that I missed this one completely!
Thanks!
Just for completeness, since I wanted to modify N
:
julia> using Base.Cartesian
julia> @generated function foo(A::AbstractArray{T, N}) where {T, N}
quote
@nloops $N i A begin
println("Do something with the indices")
end
end
end
foo (generic function with 1 method)
julia> @generated function foo2(A::AbstractArray{T, N}) where {T, N}
N2 = N - 1
quote
@nloops $N2 i A begin
println("Do something with the indices")
end
end
end
foo2 (generic function with 1 method)
julia> foo(randn((3,3)))
Do something with the indices
Do something with the indices
Do something with the indices
Do something with the indices
Do something with the indices
Do something with the indices
Do something with the indices
Do something with the indices
Do something with the indices
julia> foo2(randn((3,3)))
Do something with the indices
Do something with the indices
Do something with the indices