I want to know if a list contains any value more than once. Here's what I have.
has_dupes(List) ->
has_dupes(List, []).
has_dupes([Item|List], Seen) ->
case lists:filter(fun(Elem) -> Elem == Item end, Seen) of
[] ->
has_dupes(List, [Item|Seen]);
_ ->
true
end;
has_dupes([], _Seen) ->
false.
Is there a simpler/more concise/more idiomatic way to do this? I'm pretty new at the Erlang.
erlang:length(List) == sets:size(sets:from_list(List)).
What about this possible solution?
has_dupes([H|T]) ->
case lists:member(H, T) of
true -> true;
false -> has_dupes(T)
end;
has_dupes([]) -> false.
Had a 2 million element list of binaries to check. Ran these two versions for speed. usort appears to win, 6 seconds vs 316 seconds.
14> timer:tc(fun() -> erlang:length(X) == erlang:length(lists:usort(X)) end).
{6825493,false}
15> timer:tc(fun() -> erlang:length(X) == sets:size(sets:from_list(X)) end).
{316297882,false}
Related
This question already has answers here:
Use of function in Guard not allowed. Suggestions for alternate implementation wanted
(2 answers)
Closed 6 years ago.
I was trying to write my own filter function and ran into an error. The code:
filter_acc(_, [], Result) -> Result;
filter_acc(F, [H|T], Result) when F(H) =:= true -> filter_acc(F, T, [H | Result]).
filter(F, L) -> filter_acc(F, L, []).
The error:
my_functions.erl:11: illegal guard expression
error
Can functions not be evaluated as part of guard expressions? If not, how is this to be done?
You can achieve it like this (only with function clause, no need of guards) but I am afraid it has few interest.
1> FA = fun FA(_,[H],true,R) -> [H|R];
1> FA(_,[_],_,R) -> R;
1> FA(F,[H1,H2|T],true,R) -> FA(F,[H2|T],F(H2),[H1|R]);
1> FA(F,[_,H2|T],_,R) -> FA(F,[H2|T],F(H2),R) end.
#Fun<erl_eval.28.50752066>
2> Filter = fun(_,[]) -> []; (F,L= [H|_]) -> FA(F,L,F(H),[]) end.
#Fun<erl_eval.12.50752066>
3> Filter(fun(X) -> X > 4 end,[1,2,5,hello,"Joe"]).
["Joe",hello,5]
4>
Using Erlang, I have the following expression:
{add,{var,a},{mul,{num,2},{var,b}}}
and I am using lists:keymember to see whether the letter b is within the expression as such:
lists:keymember(b,2,[expr])
However, it doesn't look within the third tuple '{mul,{num,2},{var,b}' as that is a separate tuple. Is there a function that will search through the whole tuple and tuples within?
Thanks
As far I as I know there are no such functions. Probably you will have to implement some custom solution using recursion. Here is my example:
-module(test).
-compile(export_all).
find(_, []) -> false;
find(E, T) when is_tuple(T) ->
find(E, tuple_to_list(T));
find(E, [H|T]) ->
case find(E, H) of
false -> find(E, T);
true -> true
end;
find(V, E) -> V == E.
And usage:
1> test:find(b, {add,{var,a},{mul,{num,2},{var,b}}}).
true
2> test:find(b, {add,{var,a},{mul,{num,2},{var,c}}}).
false
Please review your code.
Line1: this is a tree, not a list.
Line2: expr is not a variable.
What you want to do is a visitor function, and you'll have to write it yourself.
A very good start would be to read this.
I am trying to create a very simple recursive function to delete all element that have a particular value that the user decides on from a list.
In haskell I would use guards and do:
deleteAll_rec _ [] = []
deleteAll_rec del (x:xs) | del==x = deleteAll_rec del xs
| otherwise = x:deleteAll_rec del xs
I am trying to code up an Erlang equivalent, however, I am not sure how to handle the otherwise case:
deleteAll_rec(_, []) -> [];
deleteAll_rec(DEL, [X|XS]) when DEL =:= X -> deleteAll_rec(DEL, XS).
I was wondering if someone can demonstrate how this can be done?
Many thanks in advance!
The otherwise becomes a separate clause in Erlang:
delete_all_rec(_, []) -> [];
delete_all_rec(Del, [Del|Xs]) ->
delete_all_rec(Del, Xs);
delete_all_rec(Del, [X|Xs]) ->
[X|delete_all_rec(Del, Xs)].
An alternative is to use an if like:
delete_all_rec(_, []) -> [];
delete_all_rec(Del, [X|Xs]) ->
if Del =:= X ->
delete_all_rec(Del, Xs);
true ->
[X|delete_all_rec(Del, Xs)]
end.
The resultant code is the same but I think the first version looks better. Whether you put the terminating case first or last is irrelevant in this example, I prefer putting it last.
Two tables are related and I want to write function to delete all records in these two tables, but the output indicates that I can't do that. Is the low efficient choice to delete record one by one is the only available choice?
clear_gyne()->
R = execute_mnesia_transaction(
fun()->
mnesia:clear_table(bas_gyne),
mnesia:clear_table(bas_gyne_property)
end),
R.
execute_mnesia_transaction(TxFun) ->
%% Making this a sync_transaction allows us to use dirty_read
%% elsewhere and get a consistent result even when that read
%% executes on a different node.
%% case worker_pool:submit(
%% fun () ->
Result_a = case mnesia:is_transaction() of
false -> DiskLogBefore = mnesia_dumper:get_log_writes(),
Res = mnesia:sync_transaction(TxFun),
DiskLogAfter = mnesia_dumper:get_log_writes(),
case DiskLogAfter == DiskLogBefore of
true -> Res;
false -> {sync, Res}
end;
true -> mnesia:sync_transaction(TxFun)
end,
case Result_a of
{sync, {atomic, Result}} -> mnesia_sync:sync(), Result;
{sync, {aborted, Reason}} -> throw({error, Reason});
{atomic, Result} -> Result;
{aborted, Reason} -> throw({error, Reason})
end.
execute_mnesia_transaction is copied from rabbitmq project's source code.
The output is
bas_store:clear_gyne().
** exception throw: {error,{aborted,nested_transaction}}
in function bas_store:execute_mnesia_transaction/1 (src/bas_store.erl, line 29)
mnesia:clear_table/1 is categorized into schema transactions, so can not be nested in another transaction.
cf. mnesia:clear_table
http://erlang.org/pipermail/erlang-questions/2005-August/016582.html
Is there a better way to implement Racket's ormap in Erlang than:
ormap(_, []) -> false;
ormap(Pred, [H|T]) ->
case Pred(H) of
false -> ormap(Pred, T);
_ -> {ok, Pred(H)}
end.
Looks pretty good to me. I'm not sure how smart Erlang is about optimizing these things, but you might want to actually bind the non-false pattern match to a variable, and avoid recomputing Pred(H).
ormap(_, []) -> false;
ormap(Pred, [H|T]) ->
case Pred(H) of
false -> ormap(Pred, T);
V -> {ok, V}
end.
The Racket version doesn't include the ok symbol, but that seems like the Erlangy thing to do so I don't see anything wrong with it. You might similarly expect Pred to return an attached ok symbol for the non-false case, in which case:
V -> V
or
{ok, V} -> {ok, V}
should work.