Skip to content

Instantly share code, notes, and snippets.

@alco
Last active September 25, 2022 19:56
Show Gist options
  • Save alco/7607977 to your computer and use it in GitHub Desktop.
Save alco/7607977 to your computer and use it in GitHub Desktop.
defmodule L do
# lc x inlist [0, 1], y inlist [:a, :b], do: {x, y}
defmacro do_list(list) do
args = 1..length(list)
|> Enum.map(fn x -> binary_to_atom(<<?a + x :: utf8>>) end)
|> Enum.map(fn x -> {x, [], :Elixir} end) # this creates AST nodes for variables
pairs = Enum.zip(args, list)
|> Enum.map(fn {v, lst} ->
quote do
unquote(v) inlist unquote(lst)
end
end)
quote do
lc unquote_splicing(pairs), do: {unquote_splicing(args)}
end
end
end
iex> Macro.expand quote(do: L.do_list([[0, 1], [:a, :b], ['x', 'y']])), __ENV__
{:lc, [],
[{:inlist, [], [{:b, [], Elixir}, [0, 1]]},
{:inlist, [], [{:c, [], Elixir}, [:a, :b]]},
{:inlist, [], [{:d, [], Elixir}, ['x', 'y']]},
[do: {:{}, [], [{:b, [], Elixir}, {:c, [], Elixir}, {:d, [], Elixir}]}]]}
# vs
iex> Macro.expand quote(do: lc(x inlist [0, 1], y inlist [:a, :b], do: {x, y})), __ENV__
{:lc, [],
[{:inlist, [], [{:x, [], Elixir}, [0, 1]]},
{:inlist, [], [{:y, [], Elixir}, [:a, :b]]},
[do: {{:x, [], Elixir}, {:y, [], Elixir}}]]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment