How do I match multiple atoms in Erlang? - erlang

How do I do the below, for example
A = atom_a,
case A of
atom_b or atom_c ->
%do something here;
atom a ->
%do something else!
end.

You can use guards:
A = 'atom_a',
case A of
B when B =:= 'atom_b'; B =:= 'atom_c' ->
%do something here;
'atom_a' ->
%do something else!
end.

Try the following:
case is_special_atom(A) of
true ->
%do something here;
false ->
%do something else!
end.
is_special_atom(atom_b) -> true;
is_special_atom(atom_c) -> true;
is_special_atom(_) -> false.

Related

Erlang syntax error before: 'end' in line 55

Cant find the syntax error, i searched for misplaced/missing ";" , "," , "end" and also searched for missing parentheses but no luck.
Any ideas?
PD: Sorry for bad English and Spanglish code
partida(ID,Tablero,Turno,Name1,Psocket1,Name2,Psocket2,SpectList) ->
case (Psocket1 == " ") of
true -> F = fun() -> case mnesia:read(juegos,ID) of
[P1] ->
case mnesia:read(nombre,P1#juegos.jg1) of
[] -> exit(normal);
[A] -> P2 = A#nombre.psocket
end,
case mnesia:read(nombre,P1#juegos.jg2) of
[] -> exit(normal);
[B] -> P3 = B#nombre.psocket
end,
Res = {P1#juegos.jg1,P2,P1#juegos.jg2,P3,P1#juegos.spect};
_ -> Res = ok,exit(normal)
end,
Res end,
{atomic,Arg} = mnesia:transaction(F),
partida(ID,Tablero,Turno,element(1,Arg),element(2,Arg),element(3,Arg),element(4,Arg),element(5,Arg))
end,
receive
case Jugada of
[Pj,"bye"] -> ok;
[Pj,F] -> Posicion = element(1,string:to_integer(F)),
case (Name1 == Pj) and ((Turno rem 2) == 1) of
true -> case not(Posicion == error) and (Posicion < 10) of
true -> ok;%%jugada valida
_ -> ok %%Jugada ilegal
end;
false ->ok %%No es tu turno
end,
case (Name2 == Pj) and ((Turno rem 2) == 0) of
true -> case (not(Posicion == error) and (Posicion < 10)) of
true ->ok; %%jugada valida
_ -> ok %%Jugada ilegal
end;
false -> ok %%No es tu turno
end
end
end, %% Line 55
ASD = get_spects(ID),partida(ID,Tablero,Turno,Name1,Psocket1,Name2,Psocket2,ASD).
You have a syntax error in receive clause.
1> case oops of _ -> ok end. % correct
ok
2> receive (case oops of _ -> ok end) end.
* 1: syntax error before: 'end'
receive statement is used for reading Erlang messages of the process. Here you are not waiting for any message and you are doing something in body of receive clause! If you don't want to check the message but you want to do something after receiving first message, I recommend to use _ for pattern matching:
3> receive _ -> (case oops of _ -> ok end) end.
%% Waits for a message
Actually you can have no receive clause, but like this:
4> receive after 1000 -> done end. %% Sleeps 1000 ms and does not care about any incoming message
done
But you can't write code in receive clause without any pattern matching.

Erlang - pattern matching predicate

To know if particular expression matches specified pattern I can write in erlang something like following:
case <expression> of
<pattern> -> true;
_ -> false
end
For example:
case {1, 2, 3} of
{_, 2, _} -> true;
_ -> false
end
Is there a way to write it in more compact way? Something like:
is_match(<pattern>, <expression>)
No, there's no such construct. You could define a macro to do it:
-define(is_match(Pattern, Expr), case Expr of Pattern -> true; _ -> false end).
another macro :o) -define (IS_MATCH(PAT,EXP), catch(PAT = EXP) == EXP end). with no case, but I am not sure that a catch is better.

Racket ormap in erlang

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.

How can I detect if a list contains duplicates?

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}

Erlang - Anonymouos Function

If i call the test(), it doesnt work. Can someone explain this ?.
-module(anony).
-export([test/0, test1/0]).
test1() -> "hello".
test() ->
C = fun(F) -> Val = F(), io:format("~p ", [Val]) end,
lists:foreach(debug, [test1]).
test1 on its own is simply an atom, not a reference to the local function. To create a reference to the function use fun Function/Arity as below.
-module(anony).
-export([test/0, test1/0]).
test1() -> "hello".
test() ->
C = fun(F) -> Val = F(), io:format("~p ", [Val]) end,
lists:foreach(C, [fun test1/0]).
You could also construct an anonymous function that calls test1 like this: fun() -> test1() end, but there's no reason to that unless you have additional values you want to pass in or the like.
The other two answers do actually answer the question. I just want to add to them.
I expect that you want to be able to pass an atom and call the function with that name. This is not possible for local functions. It is very possible for exported functions though.
So you can do something like (my only change is to add "?MODULE:", and to change "debug" to "C"):
-module(anony).
-export([test/0, test1/0]).
test1() -> "hello".
test() ->
C = fun(F) -> Val = ?MODULE:F(), io:format("~p ", [Val]) end,
lists:foreach(C, [test1]).
First, C variable hasn't been used at all, and second you should wrap the test1 with a fun/end:
-module(anony).
-export([test/0, test1/0]).
test1() -> "hello".
test() ->
C = fun(F) -> Val = F(), io:format("~p ", [Val]) end,
lists:foreach(C, [fun() -> test1() end]).

Resources