🧪
Elixirのマクロの一覧を書き出す
intro
この記事は、「Elixir Advent Calendar 2022」カレンダー4の21日目の記事になります。
はじめに
Elixirにはマクロを定義する機能があり、言語中でも多数のマクロが使われています。
モジュールを定義するdefmodule
もマクロですし、マクロを定義するdefmacro
もマクロです。
iex(1)> h defmodule
defmacro defmodule(alias, do_block)
Defines a module given by name with the given contents.
iex(2)>
iex(3)> h defmodule
defmacro defmodule(alias, do_block)
Defines a module given by name with the given contents.
Elixirでコードを書く上で当たり前のように存在するマクロですが、標準でどれくらいのマクロがあるのか興味が沸いたため、リストアップしてみました。
マクロのリストアップ
elixirリポジトリをローカルにダウンロードし、grepツールでdefmacro
が書かれた行をリストアップします。
grepツールにはthe_silver_searcher(ag)を使います。
実行結果は下記のフォーマットで出力します(the_silver_searcherのデフォルト)
定義ファイルと行番号を出力しているため、マクロを調べる際にも役に立つと思います。
ファイルパス
行番号: ソースコード
検索結果からdefmacro
の処理じゃない部分(コメントなど)は削除しています。
実行したコマンド
$ git checkout v1.14.2
HEAD is now at 0909940b0 Release v1.14.2
$ git status
HEAD detached at v1.14.2
$ ag "defmacro " lib/elixir/lib/
実行結果
マクロ一覧
lib/elixir/lib/agent.ex
202: defmacro __using__(opts) do
lib/elixir/lib/application.ex
392: defmacro __using__(_) do
530: defmacro compile_env(app, key_or_path, default \\ nil) do
570: defmacro compile_env!(app, key_or_path) do
lib/elixir/lib/behaviour.ex
21: defmacro defcallback(spec) do
29: defmacro defmacrocallback(spec) do
91: defmacro __using__(_) do
lib/elixir/lib/bitwise.ex
26: defmacro __using__(options) do
lib/elixir/lib/config.ex
209: defmacro config_env() do
232: defmacro config_target() do
263: defmacro import_config(file) do
lib/elixir/lib/dict.ex
21: defmacro __using__(_) do
lib/elixir/lib/dynamic_supervisor.ex
247: defmacro __using__(opts) do
lib/elixir/lib/gen_event.ex
90: defmacro __using__(_) do
lib/elixir/lib/gen_server.ex
750: defmacro __using__(opts) do
853: defmacro __before_compile__(env) do
lib/elixir/lib/inspect.ex
520: defmacro __deriving__(module, struct, options) do
lib/elixir/lib/io/ansi.ex
4: defmacro defsequence(name, code, terminator \\ "m") do
lib/elixir/lib/kernel/special_forms.ex
62: defmacro unquote(:{})(args), do: error!([args])
82: defmacro unquote(:%{})(args), do: error!([args])
154: defmacro unquote(:%)(struct, map), do: error!([struct, map])
371: defmacro unquote(:<<>>)(args), do: error!([args])
493: defmacro unquote(:.)(left, right), do: error!([left, right])
554: defmacro alias(module, opts), do: error!([module, opts])
581: defmacro require(module, opts), do: error!([module, opts])
684: defmacro import(module, opts), do: error!([module, opts])
692: defmacro __ENV__, do: error!([])
700: defmacro __MODULE__, do: error!([])
708: defmacro __DIR__, do: error!([])
716: defmacro __CALLER__, do: error!([])
728: defmacro __STACKTRACE__, do: error!([])
760: defmacro ^var, do: error!([var])
765: defmacro left = right, do: error!([left, right])
786: defmacro left :: right, do: error!([left, right])
873: defmacro squared(x) do
922: defmacro squared(x) do
937: defmacro squared(x) do
974: defmacro no_interference do
995: defmacro interference do
1013: defmacro write do
1019: defmacro read do
1034: defmacro write do
1040: defmacro read do
1059: defmacro no_interference do
1080: defmacro no_interference do
1097: defmacro no_interference do
1105: defmacro interference do
1191: defmacro defadd do
1236: defmacro defkv(kv) do
1262: defmacro defkv(kv) do
1283: defmacro defkv(kv) do
1294: defmacro quote(opts, block), do: error!([opts, block])
1348: defmacro unquote(:unquote)(expr), do: error!([expr])
1364: defmacro unquote(:unquote_splicing)(expr), do: error!([expr])
1517: defmacro for(args), do: error!([args])
1652: defmacro with(args), do: error!([args])
1676: defmacro unquote(:fn)(clauses), do: error!([clauses])
1693: defmacro unquote(:__block__)(args), do: error!([args])
1771: defmacro unquote(:&)(expr), do: error!([expr])
1805: defmacro unquote(:__aliases__)(args), do: error!([args])
1812: defmacro super(args), do: error!([args])
1900: defmacro case(condition, clauses), do: error!([condition, clauses])
1929: defmacro cond(clauses), do: error!([clauses])
2238: defmacro try(args), do: error!([args])
2292: defmacro receive(args), do: error!([args])
lib/elixir/lib/kernel/utils.ex
321: defmacro defguard(args, expr) do
lib/elixir/lib/kernel.ex
1201: defmacro tap(value, fun) do
1797: defmacro left or right do
1828: defmacro left and right do
1865: defmacro !value
1867: defmacro !{:!, _, [value]} do
1880: defmacro !value do
1913: defmacro left <> right do
2005: defmacro raise(message) do
2063: defmacro raise(exception, attributes) do
2087: defmacro reraise(message, stacktrace) do
2135: defmacro reraise(exception, attributes, stacktrace) do
2400: defmacro is_struct(term) do
2436: defmacro is_struct(term, name) do
2480: defmacro is_exception(term) do
2518: defmacro is_exception(term, name) do
2568: defmacro then(value, fun) do
2909: defmacro put_in(path, value) do
2949: defmacro pop_in(path) do
2986: defmacro update_in(path, fun) do
3050: defmacro get_and_update_in(path, fun) do
3183: defmacro to_string(term) do
3196: defmacro to_charlist(term) do
3215: defmacro is_nil(term) do
3299: defmacro match?(pattern, expr) do
3425: defmacro @expr
3427: defmacro @{:__aliases__, _meta, _args} do
3431: defmacro @{name, meta, args} do
3652: defmacro binding(context \\ nil) do
3709: defmacro if(condition, clauses) do
3758: defmacro unless(condition, clauses) do
3810: defmacro destructure(left, right) when is_list(left) do
3840: defmacro first..last do
3908: defmacro first..last//step do
3972: defmacro (..) do
4003: defmacro left && right do
4043: defmacro left || right do
4126: defmacro left |> right do
4296: defmacro left in right do
4495: defmacro var!(var, context \\ nil)
4497: defmacro var!({name, meta, atom}, context) when is_atom(name) and is_atom(atom) do
4512: defmacro var!(other, _context) do
4523: defmacro alias!(alias) when is_atom(alias) do
4527: defmacro alias!({:__aliases__, meta, args}) do
4764: defmacro defmodule(alias, do_block)
4766: defmacro defmodule(alias, do: block) do
5005: defmacro def(call, expr \\ nil) do
5035: defmacro defp(call, expr \\ nil) do
5049: defmacro unless(expr, opts) do
5063: defmacro defmacro(call, expr \\ nil) do
5079: defmacro defmacrop(call, expr \\ nil) do
5239: defmacro defstruct(fields) do
5308: defmacro defexception(fields) do
5367: defmacro defprotocol(name, do_block)
5369: defmacro defprotocol(name, do: block) do
5378: defmacro defimpl(name, opts, do_block \\ []) do
5398: defmacro __using__(_opts) do
5449: defmacro __using__(_opts) do
5471: defmacro defoverridable(keywords_or_behaviour) do
5519: defmacro defguard(guard) do
5535: defmacro defguardp(guard) do
5638: defmacro __using__(opts) do
5656: defmacro __using__(_opts) do
5671: defmacro __using__(_opts) do
5688: defmacro use(module, opts \\ []) do
5761: defmacro defdelegate(funs, opts) do
5865: defmacro dbg(code \\ quote(do: binding()), options \\ []) do
5895: defmacro sigil_S(term, modifiers)
5896: defmacro sigil_S({:<<>>, _, [binary]}, []) when is_binary(binary), do: binary
5916: defmacro sigil_s(term, modifiers)
5918: defmacro sigil_s({:<<>>, _, [piece]}, []) when is_binary(piece) do
5922: defmacro sigil_s({:<<>>, line, pieces}, []) do
5942: defmacro sigil_C(term, modifiers)
5944: defmacro sigil_C({:<<>>, _meta, [string]}, []) when is_binary(string) do
5966: defmacro sigil_c(term, modifiers)
5970: defmacro sigil_c({:<<>>, _meta, [string]}, []) when is_binary(string) do
5974: defmacro sigil_c({:<<>>, _meta, pieces}, []) do
5998: defmacro sigil_r(term, modifiers)
6000: defmacro sigil_r({:<<>>, _meta, [string]}, options) when is_binary(string) do
6006: defmacro sigil_r({:<<>>, meta, pieces}, options) do
6027: defmacro sigil_R(term, modifiers)
6029: defmacro sigil_R({:<<>>, _meta, [string]}, options) when is_binary(string) do
6063: defmacro sigil_D(date_string, modifiers)
6065: defmacro sigil_D({:<<>>, _, [string]}, []) do
6103: defmacro sigil_T(time_string, modifiers)
6105: defmacro sigil_T({:<<>>, _, [string]}, []) do
6153: defmacro sigil_N(naive_datetime_string, modifiers)
6155: defmacro sigil_N({:<<>>, _, [string]}, []) do
6209: defmacro sigil_U(datetime_string, modifiers)
6211: defmacro sigil_U({:<<>>, _, [string]}, []) do
6303: defmacro sigil_w(term, modifiers)
6305: defmacro sigil_w({:<<>>, _meta, [string]}, modifiers) when is_binary(string) do
6309: defmacro sigil_w({:<<>>, meta, pieces}, modifiers) do
6333: defmacro sigil_W(term, modifiers)
6335: defmacro sigil_W({:<<>>, _meta, [string]}, modifiers) when is_binary(string) do
6456: defmacro to_char_list(arg) do
lib/elixir/lib/macro.ex
17: defmacro macro_inspect(value) do
81: defmacro sigil_x(term, [?r]) do
86: defmacro sigil_x(term, _modifiers) do
89: defmacro sigil_X(term, [?r]) do
94: defmacro sigil_X(term, _modifiers) do
257: defmacro left |> right do
1714: defmacro defmodule_with_length(name, do: block) do
1753: defmacro defmodule_with_length(name, do: block) do
lib/elixir/lib/module/types/helpers.ex
8: defmacro is_var(expr) do
lib/elixir/lib/module.ex
459: defmacro __before_compile__(_env) do
lib/elixir/lib/protocol.ex
265: defmacro def(signature)
267: defmacro def({_, _, args}) when args == [] or is_atom(args) do
271: defmacro def({name, _, args}) when is_atom(name) and is_list(args) do
304: defmacro def(_) do
388: defmacro __deriving__(module, struct, options) do
424: defmacro derive(protocol, module, options \\ []) do
lib/elixir/lib/record.ex
251: defmacro defrecord(name, tag \\ nil, kv) do
256: defmacro unquote(name)(args \\ []) do
260: defmacro unquote(name)(record, args) do
269: defmacro defrecordp(name, tag \\ nil, kv) do
lib/elixir/lib/stream/reducers.ex
58: defmacro dedup(callback, fun \\ nil) do
71: defmacro drop(fun \\ nil) do
83: defmacro drop_every(nth, fun \\ nil) do
95: defmacro drop_while(callback, fun \\ nil) do
107: defmacro filter(callback, fun \\ nil) do
119: defmacro filter_map(filter, mapper, fun \\ nil) do
131: defmacro map(callback, fun \\ nil) do
139: defmacro map_every(nth, mapper, fun \\ nil) do
151: defmacro reject(callback, fun \\ nil) do
163: defmacro scan2(callback, fun \\ nil) do
176: defmacro scan3(callback, fun \\ nil) do
185: defmacro take(fun \\ nil) do
203: defmacro take_every(nth, fun \\ nil) do
215: defmacro take_while(callback, fun \\ nil) do
227: defmacro uniq_by(callback, fun \\ nil) do
241: defmacro with_index(fun \\ nil) do
lib/elixir/lib/supervisor.ex
456: defmacro __using__(opts) do
lib/elixir/lib/task.ex
277: defmacro __using__(opts) do
おわりに
Elixir言語に標準で定義されているマクロを、ソースコードから探して一覧にしてみました。
件数を数えると、実に199個ものマクロが定義されていました!(各モジュールの__using__
マクロもカウント)
定義済マクロを使いこなして素敵なElixirライフを!
Discussion