Search code examples
cachingerlangelixirets

Filtering erlang ets tables without using guard clauses


In elixir, I would like to be able to filter an ets table using a function.

I currently have a simple ets table example in the iex shell...

iex> :ets.new(:nums, [:named_table])
:nums

iex> :ets.insert :nums, [{1}, {2}, {3}, {4}, {5}]
true

fun = :ets.fun2ms(fn {n} when n < 4 -> n end)
[{{:"$1"}, [{:<, :"$1", 4}], [:"$1"]}]
:ets.select(:nums, fun)
[1, 3, 2]

This all works as you would expect. My question relates to the function being used to query the ets table. Currently it uses a guard clause to filter for results less than 4.

I would like to know if there is a way put the guard clause syntax into the function body. For example...

iex> fun2 = :ets.fun2ms(fn {n} -> if n < 4, do: n end)

but if I do this then I get the following error...

Error: the language element case (in body) cannot be translated into match_spec
{:error, :transform_error}

Is something like this possible?


Solution

  • It turns out, this is the only way to go

    From erlang documentation

    The fun is very restricted, it can take only a single parameter (the object to match): a sole variable or a tuple. It must use the is_ guard tests. Language constructs that have no representation in a match specification (if, case, receive, and so on) are not allowed.

    More info about Match Specifications in Erlang