Skip to content

Instantly share code, notes, and snippets.

@TotalVerb
Last active August 5, 2018 01:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TotalVerb/ab823503cd6d282c0ba273d2b85125f1 to your computer and use it in GitHub Desktop.
Save TotalVerb/ab823503cd6d282c0ba273d2b85125f1 to your computer and use it in GitHub Desktop.
Go's defer with Julia macros
using MacroTools
symbolsof(ex::Symbol) = [ex]
symbolsof(ex::Expr) = ex.head == :line ? Symbol[] : vcat([symbolsof(x) for x in ex.args]...)
symbolsof(ex) = Symbol[]
reflect(ex) = Expr(:(=), ex, ex)
protected(ex) = Expr(:let, Expr(:function, :(), ex), map(reflect, symbolsof(ex))...)
const deferrals = gensym()
macro defer(ex)
quote
push!($deferrals, $(protected(ex)))
end |> esc
end
macro deferred(ex)
ex = longdef(ex)
isexpr(ex, :function) || error("call @deferred on a function")
Expr(:function, ex.args[1], quote
$deferrals = Function[]
try
$(macroexpand(ex.args[2]))
catch e
rethrow(e)
finally
for def in $deferrals
def()
end
end
end) |> esc
end
#=
EXAMPLE:
This code:
```julia
@deferred function open_lots_of_files_dangerously()
@defer println("Hello!")
for file in ["/dev/null", "/dev/zero", "this-file-doesn't-exist", "blah"]
f = open(file)
@defer close_loudly(f, file)
end
```
expands to:
```julia
function open_lots_of_files_dangerously() # In[8], line 23:
##260 = Function[] # In[8], line 24:
try # In[8], line 25:
begin # In[11], line 2:
begin # In[8], line 15:
push!(##260,let println = println
function ()
println("Hello!")
end
end)
end # In[11], line 3:
for file = ["/dev/null","/dev/zero","this-file-doesn't-exist","blah"] # In[11], line 4:
f = open(file) # In[11], line 5:
begin # In[8], line 15:
push!(##260,let close_loudly = close_loudly, f = f, file = file
function ()
close_loudly(f,file)
end
end)
end
end
end
catch e # In[8], line 27:
rethrow(e)
finally # In[8], line 29:
for def = ##260 # In[8], line 30:
def()
end
end
end
```
which does something very similar to what Go does.
=#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment