Can we store patterns for matching later?

(Reopening due to interest from people.)

I am interested in storing a pattern as a variable, or in ETS / :persistent_term – and reuse it later:

pattern = %{a: _, b: b, c: c} when is_binary(b) and is_integer(c)

# much later...

match?(pattern, map_generated_by_external_data)

And that doesn’t work.

One possible solution is defguard. I am however interested in doing this in a metaprogramming sort of way. I’ve tried this:

pattern = quote, do: %{a: _, b: b, c: c} when is_binary(b) and is_integer(c)

But I have no idea how to use it later.

Anybody else tried this?

3 Likes

I faced this problem myself a while back as well with the Solution library.

Long story short: A match can be stored as Elixir AST by wrapping it in a quote do ... end block, and these can be used as first argument to a match?, =, case or with-statement. However, because of reasons I do not understand (see here for the discussion on the Elixir issue tracker), macros in the ‘match’ position are expanded in a way that does not allow guard-expressions, even in the case of case and with that allow them to be written by hand. Which is why I ended up rolling my own scase and swith alternatives for them in the case of the Solution library.

3 Likes