Skip to content

Instantly share code, notes, and snippets.

@hunterboerner
Last active December 22, 2015 18:17
Show Gist options
  • Save hunterboerner/7bd6355f78568546c28d to your computer and use it in GitHub Desktop.
Save hunterboerner/7bd6355f78568546c28d to your computer and use it in GitHub Desktop.
# A module that will turn functions annotated with `@async :true` into functions
# that return a function that does the original function. For async goodness.
defmodule Magic do
defmacro __using__(_env) do
quote do
Module.register_attribute(__MODULE__, :async_register, accumulate: true)
@on_definition Magic
@before_compile Magic
end
end
defmacro __before_compile__(env) do
async_funcs = Module.get_attribute(env.module, :async_register)
for {name, body, args} <- async_funcs do
quote do
defoverridable ["#{unquote(name)}": unquote(length args)]
def unquote(name)(unquote_splicing(args)) do
fn -> unquote(body) end
end
end
end
end
def __on_definition__(env, _kind, name, args, _guards, body) do
async? = Module.get_attribute(env.module, :async)
Module.put_attribute(env.module, :async, false)
if async?, do: Module.put_attribute(env.module, :async_register, {name, body, args})
end
end
defmodule Thing do
use Magic
@async :true
def my_func, do: 3
@async :true
def my_other_func(x, y), do: x + y
def not_async, do: "This is not async!"
end
defmodule JustAHelper do
def purty(string) do
IO.puts IO.ANSI.format([:blue, :bright, "\n==> #{string}"])
end
end
JustAHelper.purty "Thing.my_func"
IO.inspect Thing.my_func
IO.inspect Thing.my_func.()
JustAHelper.purty "Thing.my_other_func(2, 3)"
IO.inspect Thing.my_other_func(2, 3)
IO.inspect Thing.my_other_func(2, 3).()
JustAHelper.purty "Thing.not_async"
IO.inspect Thing.not_async
⋊> ~/c/tmp elixir function_override_macro.exs
==> Thing.my_func
#Function<1.14298369/0 in Thing.my_func/0>
3
==> Thing.my_other_func(2, 3)
#Function<0.14298369/0 in Thing.my_other_func/2>
5
==> Thing.not_async
"This is not async!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment