# Error using @sync/@async within macro, help is highly appreciated

Hi there,
I would like to write a macro which just waits until a next time, if I run it on my own in a repl, it works, but if I put it into a macro, it fails with

``````ERROR: syntax: invalid let syntax around task.jl:453
``````

here the macro

``````using Dates
macro waituntil(nexttime_from_now, sleeptime_from_diff)
quote
nexttime = \$nexttime_from_now()
@sync @async begin
diff = nexttime - Dates.now()
while diff > Dates.Millisecond(0)
sleep(\$sleeptime_from_diff(diff))
diff = nexttime - Dates.now()
end
end
end
end
``````
``````julia> nexttime_from_now() = ceil(Dates.now(), Dates.Second(30))
nexttime_from_now (generic function with 1 method)

julia> sleeptime_from_diff(diff) = max(div(diff,2), Dates.Millisecond(2000))
sleeptime_from_diff (generic function with 1 method)

julia> @waituntil(nexttime_from_now, sleeptime_from_diff)
ERROR: syntax: invalid let syntax around task.jl:453
Stacktrace:
[1] top-level scope
@ REPL[25]:1
``````

doing it without a macro works…

``````begin
nexttime = nexttime_from_now()
@sync @async begin
diff = nexttime - Dates.now()
while diff > Dates.Millisecond(0)
sleep(sleeptime_from_diff(diff))
diff = nexttime - Dates.now()
end
end
end
``````

any help on how to get this into a macro is highly appreciated

running on Julia 1.8.1

EDIT: inspecting the macros it seems to be that `@sync` is generating invalid let syntax like `let Main.:(var"##sync#48") = Base.Channel(Base.Inf)` when used within a macro. Is this a bug?

If I understand things correctly - and I may not, because macro hygiene is difficult - `var"##sync#48"` comes from expansion of the `@sync` macro, and then the hygiene pass of the outer `@waituntil` turns it into `Main.:(var"##sync#48")`. Which it shouldn’t do imho, because it is clearly a local variable. So, maybe a bug? Let’s see what others say on the matter.

With this macro there shouldn’t be any unintentional side effects when the returned expression is escaped, and `nexttime` is explicitely hygiened(?)

`````` macro waituntil(nexttime_from_now, sleeptime_from_diff)
nexttime = gensym("nexttime")
esc(quote
\$nexttime = \$nexttime_from_now()
@sync @async begin
diff = \$nexttime - Dates.now()
while diff > Dates.Millisecond(0)
sleep(\$sleeptime_from_diff(diff))
diff = \$nexttime - Dates.now()
end
end
end)
end
``````

I honestly fail to see why this ought to be a macro though.

1 Like

thank you for the analysis. I agree, the macro does not make much sense here. The case is simplified – the original version indeed makes use of the macro part.