I would like to construct a match spec to select the first element from a tuple when a match is found on the second element, or the second element when the first element matches. Rather than calling ets:match twice, can this be done in one match specification?
Can multiple guards be used in an erlang ets match spec?
1k views Asked by Rich Ashworth At
2
There are 2 answers
0
On
-export([main/0]).
-include_lib("stdlib/include/ms_transform.hrl").
main() ->
ets:new(test, [named_table, set]),
ets:insert(test, {1, a, 3}),
ets:insert(test, {b, 2, false}),
ets:insert(test, {3, 3, true}),
ets:insert(test, {4, 4, "oops"}),
io:format("~p~n", [ets:fun2ms(fun({1, Y, _Z}) -> Y;
({X, 2, _Z}) -> X end)]),
ets:select(test, ets:fun2ms(fun({1, Y, _Z}) -> {first_match, Y};
({X, 2, _Z}) -> {second_match, X}
end)).
The output is:
[{{1,'$1','$2'},[],['$1']},{{'$1',2,'$2'},[],['$1']}]
[{first_match,a},{second_match,b}]
Yes.
In documentation there is example of
is_integer(X), is_integer(Y), X + Y < 4711
, or[{is_integer, '$1'}, {is_integer, '$2'}, {'<', {'+', '$1', '$2'}, 4711}]
.If you are using
fun2ms
just write funciton with two clauses.But you could also create two
MatchFunctions
. Each consist{MatchHead, [Guard], Return}
.Match head basically tells you how your data looks (is it a tuple, how many elements ...) and assigns to each element match variable
$N
whereN
will be some number. Lets say are using two-element tuples, so your match head would be{'$1', '$2'}
.Now lets create guards: For first function we will assume something simple, like first argument is integer greater than 10. So first guard will be
{is_integer, '$2'}
, and second{'>', '$2', 5}
. In both we use firs element of our match head'$2'
. Second match function would have same guards, but with use of'$1'
.And at last the return. Since we would like to just return one element, for first function it will be
'$1'
, and for second'$2'
(returning tuple is little more complicated, since you would have to wrap it in additional on-element tuple).So finally, when put together it gives us
Havent had too much time to test it all, but it should work (maybe with minor tweaks).