## The elixir `match?` source code:
defmacro match?(pattern, expr) do
success =
quote do
unquote(pattern) -> true
end
failure =
quote generated: true do
_ -> false
end
{:case, [], [expr, [do: success ++ failure]]}
end
## This is ok, `pattern` is defined in compile time.
match?({:ok, _}, {:ok, 1}) # => true
## But sometimes I need to generate the `pattern` in runtime, maybe by user input or something else.
ast = quote(do: {:ok, _})
## How to call `match?` correctly?
match?(^ast, {:ok, 1})
match?(unquote(ast), {:ok, 2}) # -> (CompileError) iex:7: unquote called outside quote
I have to disagree with @LostKobrakai here. There very much is a way to do this, because Elixir’s compilation- and metaprogramming constructs are still available at runtime. It just requires a little bit more wrapping:
iex> pattern_ast = quote do {:ok, _} end
iex> input = {:ok, 1}
iex> {result, []} = Code.eval_quoted(quote do match?(unquote(pattern_ast), unquote(input)) end)
iex> result
true
Now would you ever want to do something like this based on user input? Probably not. There are security considerations, as well as the question what a match like this based on user input would actually accomplish.