Skip to content

Instantly share code, notes, and snippets.

@koga1020
Last active January 31, 2022 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koga1020/cf0b217bb01ad29919438826df1a413e to your computer and use it in GitHub Desktop.
Save koga1020/cf0b217bb01ad29919438826df1a413e to your computer and use it in GitHub Desktop.
定義された関数を参照してmacroで新しい関数定義を追加する
$ iex -S mix
Erlang/OTP 24 [erts-12.0.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]

Interactive Elixir (1.13.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> B.__info__(:functions)
[bar: 0, foo: 0, hoge: 0, new_bar: 0, new_foo: 0, new_hoge: 0]
iex(2)> B.new_bar()
"geneareted from bar."
iex(3)> B.new_foo()
"geneareted from foo."
iex(4)> B.new_hoge()
"geneareted from hoge."
defmodule A do
defmacro __using__(_opts) do
quote do
Module.register_attribute(__MODULE__, :funs, accumulate: true)
@on_definition {A, :on_definition}
@before_compile {A, :before_compile}
end
end
def on_definition(env, kind, name, args, guards, body) do
Module.put_attribute(env.module, :funs, %{
kind: kind,
name: name,
args: args,
guards: guards,
body: body
})
end
defmacro before_compile(env) do
funs = Module.get_attribute(env.module, :funs, [])
Enum.map(funs, fn %{name: name} ->
quote do
def unquote(:"new_#{name}")() do
"geneareted from #{unquote(name)}."
end
end
end)
end
end
defmodule B do
use A
def foo(), do: "foo"
def bar(), do: "bar"
def hoge(), do: "hoge"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment