check for item in list in Erlang - erlang

I'm trying to make check function in Erlang
I have one word and list of word
list_word() ->
["bad1", "bad2", "bad3"].
And I'm trying to check if this word in list return true except return false
example :
check_list() ->
badword = list_word(),
if "bad1" == badword ->
%% do some thing
in this case first word in list but second word not and I wan't it to return true
check_list() ->
badword = list_word(),
if "bad1 test" == badword ->
%% do some thing
how can I do it ?

Look at lists:member/2 — it is implemented as a BIF so it's very fast.
case lists:member("bad1", list_word()) of
true ->
%% do something
;
false ->
ok
end.
Edit:
For your second example you can do something like:
Words = list_word(),
Found = fun(Word) -> lists:member(Word, Words) end,
BadWords = string:tokens("bad1 test", " "),
case lists:any(Found, BadWords) of
true ->
%% do something
;
false ->
ok
end.

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: syntax error before: ","word"

I have the following functions:
search(DirName, Word) ->
NumberedFiles = list_numbered_files(DirName),
Words = make_filter_mapper(Word),
Index = mapreduce(NumberedFiles, Words, fun remove_duplicates/3),
dict:find(Word, Index).
list_numbered_files(DirName) ->
{ok, Files} = file:list_dir(DirName),
FullFiles = [ filename:join(DirName, File) || File <- Files ],
Indices = lists:seq(1, length(Files)),
lists:zip(Indices, FullFiles). % {Index, FileName} tuples
make_filter_mapper(MatchWord) ->
fun (_Index, FileName, Emit) ->
{ok, [Words]} = file:consult(FileName), %% <---- Line 20
lists:foreach(fun (Word) ->
case MatchWord == Word of
true -> Emit(Word, FileName);
false -> false
end
end, Words)
end.
remove_duplicates(Word, FileNames, Emit) ->
UniqueFiles = sets:to_list(sets:from_list(FileNames)),
lists:foreach(fun (FileName) -> Emit(Word, FileName) end, UniqueFiles).
However, when i call search(Path_to_Dir, Word) I get:
Error in process <0.185.0> with exit value:
{{badmatch,{error,{1,erl_parse,["syntax error before: ","wordinfile"]}}},
[{test,'-make_filter_mapper/1-fun-1-',4,[{file,"test.erl"},{line,20}]}]}
And I do not understand why. Any ideas?
The Words variable will match to content of the list, which might not be only one tuple, but many of them. Try to match {ok, Words} instead of {ok, [Words]}.
Beside the fact that the function file:consult/1 may return a list of several elements so you should replace {ok,[Words]} (expecting a list of one element = Words) by {ok,Words}, it actually returns a syntax error meaning that in the file you are reading, there is a syntax error.
Remember that the file should contain only valid erlang terms, each of them terminated by a dot. The most common error is to forget a dot or replace it by a comma.

Erlang: find word from list and return True

How can I make function to search for a word in list and return true if word in list.
Example :
find(string) ->
List = ["bye", "hello", "hi"],
case string in List of
true ->
true;
_ ->
false
end.
find("hi there, how are you today?").
And the text is : "hi there, How are you today?"
it should return true cuz hi in list.
1> F = fun(String) -> List = ["bye", "hello", "hi"], lists:any(fun(S) -> lists:member(S, List) end, string:tokens(String, " ,.?!")) end.
#Fun<erl_eval.6.54118792>
2> F("hi, what did you tried so far?").
true

Returning specific xml tag with erlang

get_currency() ->
URL = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22GBPEUR%22)&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys",
{Result, Info} = httpc:request(URL),
case Result of
error ->
{Result, Info};
ok ->
{{_Protocol, Code, _CodeStr}, _Attrs, WebData} = Info,
WebData
end.
extract_text(Content) ->
Item = hd(Content),
case element(1, Item) of
xmlText -> Item#xmlText.value;
_ -> ""
end.
analyze_info(WebData) ->
ToFind = [rate],
Parsed = element(1, xmerl_scan:string(WebData)),
Children = Parsed#xmlElement.content,
ElementList = [{El#xmlElement.name, extract_text(El#xmlElement.content)} || El <- Children, element(1, El) == xmlElement],
lists:map(fun(Item) -> lists:keyfind(Item, 1, ElementList) end, ToFind).
the above is the code im using to try to extract the contents of the tag from the url http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22GBPEUR%22)&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys.
here is what i do in the shell.
inets:start().
XML = scrapetest:get_currency().
scrapetest:analyze_info(XML).
and the return i get is simply "false". Im not sure what im doing wrong.
Just add some logs to your code.
Eg. adding io:format("~p~n", [ElementList]), - will show you that ElementList contains only result tag, and you should go one level deeper in your list comprehension to get tag named rate
This is common advice.
In your case, seems that better decision is recursive find function (if you want to write some code)
or use some batteries, like xmerl_xpath
Just example for another analyze_info :
analyze_info(WebData) ->
Parsed = element(1, xmerl_scan:string(WebData)),
xmerl_xpath:string("//Rate/text()", Parsed).
This will return:
[{xmlText,[{'Rate',2},{rate,1},{results,1},{query,1}],
1,[],"1.1813",text}]

list match (last N character match)

I am writing hg(mercurial)'s client now. For tags commands, the reponse is as follows:
<<"adding a\na\ncommitted changeset
0:44108598f0ec643e7d90e9f18a2b6740401a510a\ntip
1:ce4daf41b6ae\nmy tags
0:44108598f0ec\ntest tag 0:44108598f0ec
local\n">>.
The python's related code is as follows:
t = []
for line in out.splitlines():
taglocal = line.endswith(' local')
if taglocal:
line = line[:-6]
name, rev = line.rsplit(' ', 1)
rev, node = rev.split(':')
t.append((name.rstrip(), int(rev), node, taglocal))
return t
I have to check everyline for "local" postfix, but the compiler give syntax error. How to write correctly and elegant.
error message:
src/emercurial_client.erl:763: illegal pattern
Code
process_tags(List)->
process_tags(List,[]).
process_tags([],Result)->
lists:reverse(Result);
process_tags([Line|Rest],Result) ->
B = binary_to_list(Line),
A = process_tags_line(B),
process_tags(Rest,[A|Result]).
process_tags_line(New_list ++"local")-> %%<-----error here
process_tags_line(New_list);
process_tags_line(New_list)->
%% case List of
%% Data ++ " local" -> %%<-----also match error
%% New_list = Data;
%% _ ->
%% New_list = List
%% end,
[Name,Part2] = string:tokens(Data," "),
[Rev,Node] = string:tokens(Part2,":"),
{trim(Name),love_misc:to_integer(Rev),
node,New_list}.
After modification, it is follows:
process_tags(List)->
List_b = binary:split(List,<<$\n>>,[global]),
Result = process_tags(List_b,[]),
%% error_logger:info_report([client_process_tags,Result]),
Result.
process_tags([],Result)->
lists:reverse(Result);
process_tags([<<>>],Result)->
lists:reverse(Result);
process_tags([Line|Rest],Result) ->
B = binary_to_list(Line),
A = process_tags_line(B),
process_tags(Rest,[A|Result]).
process_tags_line(List) ->
%% error_logger:info_report([client_tags_line_1,List]),
case lists:suffix(" local",List) of
true ->
New_list = lists:sublist(List,1,length(List)-7);
_ ->
New_list = List
end,
{Name,Part2} = rsplit(New_list,$\s),
{Rev,Node} =
rsplit(Part2,$:),
Rev_a = string:substr(Rev,1,length(Rev)-1),
{love_misc:trim(Name),love_misc:to_integer(Rev_a),Node,New_list}.
rsplit(A,Char)->
Index = string:rchr(A,Char),
lists:split(Index,A).
As pointed in documentation, you can match only prefixes in similar way (which in fact just a syntactic sugar).
I'd suggest you to use function lists:suffix
So, you can rewrite your code in such way:
New_list =
case lists:suffix(" local", List) of
true ->
Data;
false ->
List
end
Note, that case expressions returns values, so you can bind variable New_List only once - with result of case expression, instead of binding in each branch of case expression
I think you cannot use this pattern matching because of the underlying structure of a list ([A|[B|[....|[]...]]).
The reverse works so you can do something like
process_tags_line(List) ->
process_tags_line_1(lists:reverse(List)).
process_tags_line1(" lacol"++L) -> process_tags_line1(L);
process_tags_line1(L) ->
New_list = lists:reverse(L),
[Name,Part2] = string:tokens(Data," "),
[Rev,Node] = string:tokens(Part2,":"),
{trim(Name),love_misc:to_integer(Rev),node,New_list}.
But the simplest thing may be to use lists:suffix(L1,L2)...

Resources