Hi there!
From what you know, decorators in Elixir can be implemented, but it gets cumbersome and you shouldn’t do it. Below you will see a new approach that is very simple. It is not exactly decorators (the module attributes syntax is not used) but a decent replacement for them: wrappers.
defmodule Wrapper do
defmacro apply(call, [do: block]) do
{wrapper, _opts, args} = call
func = makefun(do: block)
{wrapper, [], [:wraps, func] ++ args}
end
def makefun(do: block), do:
{:fn, [], [{:->, [], [[], block]}]}
end
defmodule Ex do
require Wrapper
# a wrapper that increments each of 2 values returned
def incr(:wraps, f, x, y) do
# x and y are unused here
{a, b} = f.()
{a+1, b+1}
end
def f(x, y) do
incr(x, y) |> Wrapper.apply do
{x, y}
end
end
# a convenience macros for incr wrapper
# just showing it can have the same name (incr)
defmacro incr(x,y, do: block) do
{wrapper, _opts, _args} = quote do Ex.incr end
func = Wrapper.makefun(do: block)
{wrapper, [], [:wraps, func, x, y]}
end
def g(x, y) do
incr(x, y) do
{x, y}
end
end
end