Elixir ETS Match Specs
A match specification is a small list of tuples that tells :ets.select which rows to return. Each entry holds a pattern, a list of guard tests, and a list of values to return.
Keep only rows over 18
Select names from rows whose second item is over 18, then sort the names.
table = :ets.new(:scores, [:set, :public])
:ets.insert(table, {"ana", 20})
:ets.insert(table, {"bo", 15})
:ets.insert(table, {"cy", 22})
IO.inspect(Enum.sort(:ets.select(table, [{{:"$1", :"$2"}, [{:>, :"$2", 18}], [:"$1"]}])) )Match one exact age
Change the guard to an equality test and select the matching name.
table = :ets.new(:scores, [:set, :public])
:ets.insert(table, {"ana", 20})
:ets.insert(table, {"bo", 15})
:ets.insert(table, {"cy", 22})
IO.inspect(Enum.sort(:ets.select(table, [{{:"$1", :"$2"}, [{:==, :"$2", 20}], [:"$1"]}])) )Return ages for every row
An empty guard list matches every row, and the result list picks the age from each row.
table = :ets.new(:scores, [:set, :public])
:ets.insert(table, {"ana", 20})
:ets.insert(table, {"bo", 15})
:ets.insert(table, {"cy", 22})
IO.inspect(Enum.sort(:ets.select(table, [{{:"$1", :"$2"}, [], [:"$2"]}])) )Example
table = :ets.new(:scores, [:set, :public])
:ets.insert(table, {"ana", 20})
:ets.insert(table, {"bo", 15})
:ets.insert(table, {"cy", 22})
:ets.insert(table, {"dan", 18})
adults = Enum.sort(:ets.select(table, [{{:"$1", :"$2"}, [{:>, :"$2", 18}], [:"$1"]}]))
IO.inspect(adults)
IO.puts("count: #{length(adults)}")Key points
- Pattern: The pattern describes a row, with :"$1" standing for the first item and :"$2" for the second item.
- Guard: The guard list holds tests that a row must pass, such as checking that an age is over 18.
- Result: The result list holds the values to return for each row that passes.
- Match all: An empty guard list matches every row in the table.
- Hand-written specs: Match specifications in this course are written by hand as tuples.
In this example, four rows are inserted into a set table. A match specification keeps only rows whose age is over 18 and returns their names. The sorted names are printed, and the count is 2 because the row aged 18 does not pass.
Note
Sort the result when order matters, because :ets.select does not promise an order for a set table.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
In a match specification, what does the guard [{:>, :"$2", 18}] do?