[Probably] A Naive Macro Interpolation Doubt

Hellos,

All that I want to do is a basic a macro to access some arrays. Here is the working code with expressions:

``````# works
let
N = 5
a = zeros(N)
b = collect(1:N)
myexp = quote
for i = 1:\$N
\$a[i] = 2*\$b[i]
end
end
eval(myexp)
a
end
``````

Here my attempt to make a macro

``````# i wish it could work
macro myLoop(a, b, N)
quote
a, b, N = esc.((a,b,N))
for i = 1:\$N
\$a[i] = 2*\$b[i]
end
end
end
function mytest()
N = 7
a = zeros(N)
b = collect(1:N)
@myLoop a b N
a
end
mytest()
``````

I got an error that N does not exist:

``````ERROR: UndefVarError: N not defined
Stacktrace:
[1] mytest()
@ Main ./Untitled-1:19
[2] top-level scope
@ Untitled-1:31
``````

Iâ€™m sure Iâ€™m doing a very basic mistake, but I canâ€™t figure out looking at examples on discourse.

Hereâ€™s the problemâ€“your macro is producing code which tries to call the `esc` function on some local variable named `N` which doesnâ€™t exist. `esc` is just like any other functionâ€“it doesnâ€™t know that you actually want to interpolate the value of `N` (thatâ€™s what the `\$` syntax is for).

Hereâ€™s one version that works:

``````julia> macro myLoop(a, b, N)
quote
for i = 1:\$(esc(N))
\$(esc(a))[i] = 2*\$(esc(b))[i]
end
end
end
``````

or, if you prefer:

``````julia> macro myLoop(a, b, N)
quote
a, b, N = (\$(esc(a)), \$(esc(b)), \$(esc(N)))
for i = 1:N
a[i] = 2*b[i]
end
end
end

``````
1 Like

A simpler change is to lift the `esc` calls out of the `quote`

``````macro myLoop(a, b, N)
a, b, N = esc.((a,b,N))
quote
for i = 1:\$N
\$a[i] = 2*\$b[i]
end
end
end
``````
2 Likes