I'm trying to write a simple swap!
macro in Julia, to understand the macro system. Here's my code so far:
macro swap!(x, y)
quote
local tmp = $(esc(y))
$x = $(esc(y))
$y = tmp
end
end
a = 1
b = 2
@swap!(a, b)
# prints: a: 1, b: 2
println("a: $a, b: $b")
This runs without error, but isn't actually changing the values. Julia doesn't seem to have a function that just expands macros without executing them (as far as I can see), so this is hard to debug.
The equivalent quote in a REPL seems to work as expected:
julia> a = 1
1
julia> a_sym = :a
:a
julia> a_sym
:a
julia> b = 2
2
julia> b_sym = :b
:b
julia> eval(quote
tmp = $a_sym
$a_sym = $b
$b_sym = tmp
end)
1
julia> a
2
julia> b
1
What am I doing wrong?
I think you probably want something like below but are getting messed up by hygiene. The trick is to escape correctly.
macro swap(x,y)
quote
local tmp = $(esc(x))
$(esc(x)) = $(esc(y))
$(esc(y)) = tmp
end
end
Here's what it looks like expanded
julia> macroexpand(quote @swap(x,y) end)
quote # none, line 1:
begin # none, line 3:
local #189#tmp = x # line 4:
x = y # line 5:
y = #189#tmp
end
end
The effect
julia> x
1
julia> y
2
julia> @swap(x,y)
julia> x
2
julia> y
1
By contrast your macro escapes y in one assignment correctly, but not in the other 2 statements and so sets the values of introduced variables rather than the intended x and y.
julia> macroexpand(quote @swap!(x,y) end)
quote # none, line 1:
begin # none, line 3:
local #208#tmp = y # line 4:
#209#x = y # line 5:
#210#y = #208#tmp
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With