我正在尋找一種方法在Erlang中使用部分元組來查找列表中的元組,類似於在Prolog中匹配的函子。例如,我想下面的代碼返回true
:在Erlang中匹配與不關心變量的元組
member({pos, _, _}, [..., {pos, 1, 2}, ...])
此代碼不能馬上工作,因爲有下列錯誤:
variable '_' is unbound
有沒有一種簡單的方法來達到同樣的效果?
我正在尋找一種方法在Erlang中使用部分元組來查找列表中的元組,類似於在Prolog中匹配的函子。例如,我想下面的代碼返回true
:在Erlang中匹配與不關心變量的元組
member({pos, _, _}, [..., {pos, 1, 2}, ...])
此代碼不能馬上工作,因爲有下列錯誤:
variable '_' is unbound
有沒有一種簡單的方法來達到同樣的效果?
對於簡單情況,最好使用已經提到的lists:keymember/3。但是,如果你真的需要member
功能,您可以自己實現這樣的:
member(_, []) ->
false;
member(Pred, [E | List]) ->
case Pred(E) of
true ->
true;
false ->
member(Pred, List)
end.
例子:
>>> member(fun ({pos, _, 2}) -> true; (_) -> false end, [..., {pos, 1, 2}, ...]).
你可以使用列表理解做到這一點:
Matches = [ Match || {Prefix, _, _} = Match <- ZeList, Prefix == pos].
使用lists:keymember/3來代替。
這是否也允許模式匹配?因爲問題不在於獲得平等匹配。 –
@WardB'list:keymember(pos,1,List)'例如在 – hdima
另一種可能性是做什麼比賽的規格做,使用原子'_'
代替原始的_
。然後,你可以寫類似如下的功能:
member(X, List) when is_tuple(X), is_list(List) ->
member2(X, List).
% non-exported helper functions:
member2(_, []) ->
false;
member2(X, [H|T]) when not is_tuple(H); size(X) =/= size(H) ->
member2(X, T);
member2(X, [H|T]) ->
case is_match(tuple_to_list(X), tuple_to_list(H)) of
true -> true;
false -> member2(X, T)
end.
is_match([], []) ->
true;
is_match(['_'|T1], [_|T2]) ->
is_match(T1, T2);
is_match([H|T1], [H|T2]) ->
is_match(T1, T2);
is_match(_, _) ->
false.
然後,您的電話現在會是:
member({pos, '_', '_'}, [..., {pos, 1, 2}, ...])
這會不會讓你像匹配模式{A, A, '_'}
(檢查前兩個地方元素是相同的),但如果你不需要變量,這應該工作。
您還可以擴展它與更多的工作使用使用類似的語法來匹配規格('$1'
,'$2'
等)的變量 - 第三個參數添加到is_match
與您目前爲止看到的變量綁定,然後爲它們編寫函數子句,類似於'_'
的子句。
當然,這不會是最快的方法。由於我沒有真正衡量的警告,我期望使用有趣的語言使用模式匹配將會提供更好的性能,但它確實使調用站點更加冗長。這是一個折衷,你必須考慮。
您可以使用列表解析宏做到這一點:
-define(member(A,B), length([0 || A <- B])>0).
?member({pos, _, _}, [{width, 17, 42}, {pos, 1, 2}, totally_irrelevant]).
這不是很有效的(它貫穿整個列表),但它是我能想到的原始語法最接近的一次。
如果你想實際提取匹配你只是刪除「長度」,並添加一個變量的元素:
-define(filter(A,B), [_E || A =_E <- B]).
可以使用ets:match
:
6> ets:match(T, '$1'). % Matches every object in the table
[[{rufsen,dog,7}],[{brunte,horse,5}],[{ludde,dog,5}]]
7> ets:match(T, {'_',dog,'$1'}).
[[7],[5]]
8> ets:match(T, {'_',cow,'$1'}).
[]
這個問題中,我希望避免這種情況,但似乎謂詞函數是將模式作爲參數傳遞的唯一方法。 –
'lists:any'實際上和這個'member'函數完全一樣:) – legoscia
@legoscia你是對的:-) – hdima