Skip to content

Instantly share code, notes, and snippets.

@alco
Created July 20, 2014 09:58
Show Gist options
  • Save alco/8ed5216d9b302f661822 to your computer and use it in GitHub Desktop.
Save alco/8ed5216d9b302f661822 to your computer and use it in GitHub Desktop.
f = fn x -> {:ok, {x, [1,x,3]}} end
import M
f.(2) |> match!({:ok, {!x, _}})
#=> 2
f.(2) |> match!({:ok, {x, [1,!x,3]}})
#=> 2
f.(2) |> match!({:ok, {13, [1,!x,3]}})
#=> ** (MatchError) no match of right hand side value: {:ok, {2, [1, 2, 3]}}
defmodule M do
defmacro match(thing, pattern, selector) do
quote do
unquote(pattern) = unquote(thing)
unquote(selector)
end
end
defmacro match!(thing, pattern) do
pattern = find_bang(pattern)
selector = Process.get(:bang)
quote do
unquote(pattern) = unquote(thing)
unquote(selector)
end
end
defp find_bang({:!, _meta, [arg]}) do
Process.put(:bang, arg)
arg
end
defp find_bang({a, meta, b}) do
{find_bang(a), meta, find_bang(b)}
end
defp find_bang({a, b}) do
{find_bang(a), find_bang(b)}
end
defp find_bang(l) when is_list(l) do
Enum.map(l, &find_bang/1)
end
defp find_bang(literal) do
literal
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment