In Julia 1.4 you can use $ to copy the current value of x into the macro. I think you see this behavior because the outer while loop has already finish before the thread from Threads.@spawn starts. By than x=3 and gets printed.
function f()
x = 0
@sync while x < 3
Threads.@spawn println($x)
x += 1
end
end
Note that at their core @spawn code and @async code are just syntax sugar of schedule(Task(() -> code)). So, normal caveats of closures apply. See:
julia> function f()
x = 0
funcs = []
while x < 3
push!(funcs, () -> println(x))
x += 1
end
for g in funcs
g()
end
end
f (generic function with 3 methods)
julia> f()
3
3
3
Thanks both. My takeaway is that @macroexpand is the key to understanding what’s going on and that much caution is required when using a variable inside @spawn that is defined outside @sync.