Erlang syntax error before: 'end' in line 55 - erlang

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.

Related

Syntax error in a guard causing undefined function

I have no idea what is the problem,
this is the code-
solve_bdd(BddTree, ListVars) ->
findRes(BddTree, maps:from_list(ListVars++[{one, 1}, {zero, 0}])).
findRes(BddTree, Map) when is_record(BddTree, node)-> Val = maps:get(getName(BddTree)), Name = getName(BddTree),
if Name=='one' or Name=='zero' -> maps:get(getName(BddTree));
(Val==1 or Val=='true') -> findRes(getRight(BddTree), Map);
(Val==0 or Val=='false') -> findRes(getLeft(BddTree), Map);
true -> error
end;
findRes(_, _) -> error.
And the shell errors-
exf.erl:183: syntax error before: '=='
exf.erl:180: function findRes/2 undefined
exf.erl:21: Warning: function getRight/1 is unused
exf.erl:22: Warning: function getLeft/1 is unused
error
When there is multiple conditions, You should group operands of or operator in parentheses:
1> false or false.
false
2> false == true or false == true.
* 1: syntax error before: '=='
2> (false == true) or (false == true).
false
Also maps:get/1 (function get in module maps which accepts 1 parameter) that you used:
maps:get( getName(BddTree) )
does not exists! But you can use maps:get/2 or maps:get/3.
Most of the time you can use case expression instead of if expression.
Also sometimes it's better to use orlese operator instead of or.
It's better to not handle anything! instead of handling both 0 and 1 and boolean types, you can use one of them and remove unnecessary checks.
By convention in Erlang it's better to write function and record names in Snake_case.
BTW, your findRes/2 function would be like:
%%% I don't know what work you expect from this function so if it's not working
%%% just like your own, try to fix it!
% findRes -> find_res
find_res(BddTree, Map) when is_record(BddTree, node) ->
% Sounds like BddTree is a record. If by `get_name/1` you just want to
% access one of it's elements, you can simply write BddTree#node.<ELEMENT_NAME>
% getName -> get_name
case get_name(BddTree) of
% you don't have to use ' character for atoms:
Name when Name == one orelse Name == zero ->
% I thinkd you've missed `Map`:
maps:get(get_name(BddTree), Map);
_ ->
% I do not use 0 and 1 and just use boolean type:
find_res(
% I thinkd you've missed `Map`:
case maps:get(get_name(BddTree), Map) of
Val when Val -> % when Val == true
% getRight -> get_right
get_right(BddTree);
_ -> % Assume false
get_left(BddTree)
end,
Map
)
end;
find_res(_, _) -> error.
And let's look at above code without comments:
find_res(BddTree, Map) when is_record(BddTree, node) ->
case get_name(BddTree) of
Name when Name == one orelse Name == zero ->
maps:get(get_name(BddTree), Map);
_ ->
find_res(
case maps:get(get_name(BddTree), Map) of
Val when Val -> % when Val == true
get_right(BddTree);
_ ->
get_left(BddTree)
end,
Map
)
end;
find_res(_, _) -> error.

What causes Erlang runtime error {undef,[{rand,uniform,[2],[]},...]}?

When executing an implementation of the Tarry distributed algorithm, a problem occurs that I don't know how to address: a crash containing the error {undef,[{rand,uniform,[2],[]}. My module is below:
-module(assign2_ex).
-compile(export_all).
%% Tarry's Algorithm with depth-first version
start() ->
Out = get_lines([]),
Nodes = createNodes(tl(Out)),
Initial = lists:keyfind(hd(Out), 1, Nodes),
InitialPid = element(2, Initial),
InitialPid ! {{"main", self()}, []},
receive
{_, List} ->
Names = lists:map(fun(X) -> element(1, X) end, List),
String = lists:join(" ", lists:reverse(Names)),
io:format("~s~n", [String])
end.
get_lines(Lines) ->
case io:get_line("") of
%% End of file, reverse the input for correct order
eof -> lists:reverse(Lines);
Line ->
%% Split each line on spaces and new lines
Nodes = string:tokens(Line, " \n"),
%% Check next line and add nodes to the result
get_lines([Nodes | Lines])
end.
%% Create Nodes
createNodes(List) ->
NodeNames = [[lists:nth(1, Node)] || Node <- List],
Neighbours = [tl(SubList) || SubList <- List],
Pids = [spawn(assign2_ex, midFunction, [Name]) || Name <-NodeNames],
NodeIDs = lists:zip(NodeNames, Pids),
NeighbourIDs = [getNeighbours(N, NodeIDs) || N <- lists:zip(NodeIDs, Neighbours)],
[Pid ! NeighbourPids || {{_, Pid}, NeighbourPids} <- NeighbourIDs],
NodeIDs.
getNeighbours({{Name, PID}, NeighboursForOne}, NodeIDs) ->
FuncMap = fun(Node) -> lists:keyfind([Node], 1, NodeIDs) end,
{{Name, PID}, lists:map(FuncMap, NeighboursForOne)}.
midFunction(Node) ->
receive
Neighbours -> tarry_depth(Node, Neighbours, [])
end.
%% Tarry's Algorithm with depth-first version
%% Doesn't visit the nodes which have been visited
tarry_depth(Name, Neighbours, OldParent) ->
receive
{Sender, Visited} ->
Parent = case OldParent of [] -> [Sender]; _ -> OldParent end,
Unvisited = lists:subtract(Neighbours, Visited),
Next = case Unvisited of
[] -> hd(Parent);
_ -> lists:nth(rand:uniform(length(Unvisited)), Unvisited)
end,
Self = {Name, self()},
element(2, Next) ! {Self, [Self | Visited]},
tarry_depth(Name, Neighbours, Parent)
end.
An undef error means that the program tried to call an undefined function. There are three reasons that this can happen for:
There is no module with that name (in this case rand), or it cannot be found and loaded for some reason
The module doesn't define a function with that name and arity. In this case, the function in question is uniform with one argument. (Note that in Erlang, functions with the same name but different numbers of arguments are considered separate functions.)
There is such a function, but it isn't exported.
You can check the first by typing l(rand). in an Erlang shell, and the second and third by running rand:module_info(exports)..
In this case, I suspect that the problem is that you're using an old version of Erlang/OTP. As noted in the documentation, the rand module was introduced in release 18.0.
Will be good if you provide the version of Erlang/OTP you are using for future questions as Erlang has changed a lot over the years. As far as i know there is no rand:uniform with arity 2 at least in recent Erlang versions and that is what you are getting the undef error, for that case you could use crypto:rand_uniform/2 like crypto:rand_uniform(Low, High). Hope this helps :)

Unable to call a function from recursive f#

trying out F#, learnt a lot today not sure if I am doing this try but I have a pattern match and recursive for some reason I am unable to call this from recursive.
// Define my active recognizer for keywords
let(|MyGirlFriend|Bye|) input =
match input with
|"lonely|"love"|"friendship"
-> MyGirlFriend
|"goodbye"|"bye"|"go"|
-> Bye
|_
-> None
I think the above code that above looks right.
//recursive response function
let rec response (token: string) (str: string) =
match token with
| Bye
-> good_bye_response ()
| RoomLocation
-> sprintf "%s" "Your call is log. Do you wish to quit?"
|_ when token.Contains("yes") -> "good bye" 0
|_ when token.Contains("no") -> answer_response ()
| None when (str.IndexOf(" ") > 0)
-> response (str.Substring(0,str.IndexOf(" ")))
(str.Substring(str.IndexOf(" ")+1))
| None when (str.IndexOf(" ") < 0)
-> response str ""
my function is :
let rec chat () =
if Break = false then
let valueInput = Console.ReadLine()
printf "Helpdesk-BCU Response --> %s \n" (response "" valueInput)
if Break = false then
chat()
else
ChatEnd()
let BCU_response (str: string) =
if (str.IndexOf(" ") > 0) then
response (str.Substring(0,str.IndexOf(" "))) (str.Substring(str.IndexOf("
")+1)) + "\n"
else
response str "" + "\n"
a couple of issues here |_ when token.Contains("yes") -> "goodbye" 0 the zero that is used in F# as an exit on here I get a red line and it states expression should have type string but has type int, I know zero is an int.
so how do I exit the recursive loop?
any sugguestion would be most welcome
It is not entirely clear what part are you struggling with, because there is quite a lot of minor issues in the code. However, a minimal working example that shows how to do the recursion is something like this:
open System
let (|Bye|Other|) input =
match input with
| "goodbye" | "bye" | "go" -> Bye
| _ -> Other
let response (token: string) =
match token with
| Bye -> false, "bye!"
| Other -> true, "sorry, I didn't get that"
let rec chat () =
let input = Console.ReadLine()
let keepRunning, message = response input
printfn ">> %s" message
if keepRunning then chat ()
The response function now also returns a Boolean - if this is true, the chat function calls itself recursively to ask another question. Otherwise, it just returns without asking more questions.

check for item in list in 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.

Implementing mod_blocking on MongooseIM

I'm trying to implement mod_blocking that will work only with mod_privacy in odbc module.
I keep getting the response:
<error code='500' type='wait'><internal-server-error0 xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error>
Here is my code:
process_blocklist_block(LUser, LServer, JIDs) ->
Filter = fun (List) ->
AlreadyBlocked = list_to_blocklist_jids(List, []),
lists:foldr(fun (JID, List1) ->
case lists:member(JID, AlreadyBlocked)
of
true -> List1;
false ->
[#listitem{type = jid,
value = JID,
action = deny,
order = 0,
match_all = true}
| List1]
end
end,
List, JIDs)
end,
case process_blocklist_block(LUser, LServer, Filter,odbc)
of
{atomic, {ok, Default, List}} ->
UserList = make_userlist(Default, List),
broadcast_list_update(LUser, LServer, Default,
UserList),
broadcast_blocklist_event(LUser, LServer,
{block, JIDs}),
{result, [], UserList};
_ -> {error, ?ERR_INTERNAL_SERVER_ERROR}
end.
process_blocklist_block(LUser, LServer, Filter, odbc) ->
F = fun () ->
Default = case mod_privacy_odbc:sql_get_default_privacy_list_t(LUser)
of
{selected, [<<"name">>], []} ->
Name = <<"Blocked contacts">>,
mod_privacy_odbc:sql_add_privacy_list(LUser, Name),
mod_privacy_odbc:sql_set_default_privacy_list(LUser, Name),
Name;
{selected, [<<"name">>], [[Name]]} -> Name
end,
{selected, [<<"id">>], [[ID]]} = mod_privacy_odbc:sql_get_privacy_list_id_t(LUser, Default),
case mod_privacy_odbc:sql_get_privacy_list_data_by_id_t(ID)
of
{selected,
[<<"t">>, <<"value">>, <<"action">>, <<"ord">>,
<<"match_all">>, <<"match_iq">>, <<"match_message">>,
<<"match_presence_in">>, <<"match_presence_out">>],
RItems = [_ | _]} ->
List = lists:map(fun mod_privacy_odbc:raw_to_item/1, RItems);
_ -> List = []
end,
NewList = Filter(List),
NewRItems = lists:map(fun mod_privacy_odbc:item_to_raw/1, NewList),
mod_privacy_odbc:sql_set_privacy_list(ID, NewRItems),
{ok, Default, NewList}
end,
ejabberd_odbc:sql_transaction(LServer, F).
I've checked all the queries. They work fine. I struggling with understanding the logic of this piece of code. What is the best way to debug this code, so i can understand when my logic is failing? Could anyone point me in the right direction?
UserList = make_userlist(Default, List),
broadcast_list_update(LUser, LServer, Default,
UserList),
broadcast_blocklist_event(LUser, LServer,
{block, JIDs}),
{result, [], UserList};
_ -> {error, ?ERR_INTERNAL_SERVER_ERROR}
if you expect
_ -> {error, ?ERR_INTERNAL_SERVER_ERROR}
is the point where server returns 'internal server error', you can just change this place to
_Otherwise ->
?WARNING_MSG("Got some unexpected result in mod_priv ~100000p",[_Otherwise]),
{error, ?ERR_INTERNAL_SERVER_ERROR)
and then look at log/ejabberd.log
Of course you need to start mongooseim with loglevel at least 3 in the ejabberd.cfg

Resources