我想构造一个匹配规范以在第二个元素上找到匹配项时从元组中选择第一个元素,或者在第一个元素匹配时选择第二个元素。而不是调用 ets:match 两次,这可以在一个匹配规范中完成吗?
2 回答
是的。
在文档中有is_integer(X), is_integer(Y), X + Y < 4711
, 或的示例[{is_integer, '$1'}, {is_integer, '$2'}, {'<', {'+', '$1', '$2'}, 4711}]
。
如果您使用的fun2ms
只是编写带有两个子句的函数。
fun({X, Y}) when in_integer(X)
andalso X > 5 ->
Y;
({X, Y}) when is_integer(Y)
andalso Y > 5 ->
X.
但您也可以创建两个MatchFunctions
. 每个组成{MatchHead, [Guard], Return}
。
匹配头基本上告诉您数据的外观(它是一个元组,有多少元素......)并分配给每个元素匹配变量$N
,其中N
将是一些数字。假设正在使用二元素元组,因此您的匹配头将是{'$1', '$2'}
.
现在让我们创建守卫:对于第一个函数,我们将假设一些简单的东西,比如第一个参数是大于 10 的整数。所以第一个守卫将是{is_integer, '$2'}
,第二个{'>', '$2', 5}
。在两者中,我们都使用了 match head 的第一个元素'$2'
。第二个匹配函数将具有相同的守卫,但使用'$1'
.
最后回归。由于我们只想返回一个元素,因此对于第一个函数,它将是'$1'
,对于第二个'$2'
(返回元组稍微复杂一些,因为您必须将其包装在额外的元素元组中)。
所以最后,当放在一起时,它给了我们
[ _FirstMatchFunction = {_Head1 = {'$1', '$2'},
_Guard1 = [{is_integer, '$2},
{'>', '$2', 5}], % second element matches
_Return1 = [ '$1']}, % return first element
_SecondMatchFunction = {_Head2 = {'$1', '$2'},
_Guard2 = [{is_integer, '$1},
{'>', '$1', 5}], % second element matches
_Return2 = [ '$2']} ] % return first element
Havent 有太多时间来测试这一切,但它应该可以工作(也许有一些小的调整)。
-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)).
输出是:
[{{1,'$1','$2'},[],['$1']},{{'$1',2,'$2'},[],['$1']}]
[{first_match,a},{second_match,b}]