Erlang Bit Syntax pattern matching works in shell but not as passed argument - parsing

I am trying to make a simple UDP packet decoder.
packet_decoder(Packet)->
<<Opts:8,MobIdLength:8,MobId:64,MobIdType:8,MgeType:8,SeqNum:16,Rest/binary>> = Packet,
io:format("Options:~p~n",Opts),
io:format("MobIdLength:~p~n",MobIdLength),
io:format("MobId:~p~n",MobId),
io:format("MobIdType:~p~n",MobIdType),
io:format("MgeType:~p~n",MgeType),
io:format("SeqNum:~p~n",SeqNum).
Packet is passed by a receive loop:
rcv_loop(Socket) ->
inet:setopts(Socket, [{active, once}, binary]),
io:format("rcvr started:~n"),
receive
{udp, Socket, Host, Port, Bin} ->
packet_decoder(Bin),
rcv_loop(Socket)
end.
I keep getting(following error edited 9/7/12 9:30 EST):
** exception error: no match of right hand side value
<<131,8,53,134,150,4,149,0,80,15,1,2,1,2,0,16,80,71,115,
52,80,71,115,53,24,63,227,197,211,...>>
in function udp_server:packet_decoder/1
called as udp_server:packet_decoder(<<131,8,53,134,150,4,149,0,80,15,
1,2,1,2,0,16,80,71,115,52,80,71,
115,53,24,63,227,197,...>>)
in call from udp_server:rcv_loop/1
in call from udp_server:init/0
If I create the same variable in the Erlang shell as a binary, i.e.
Packet = <<131,8,53,134,150,4,149,0,80,15,1,2,1,2,0,16,80,71,115,52,80,71,115,53,24,63,227,197,211,228,89,72,0,0,0,0,0,0,0,16,0,5,5,32,1,4,255,159,15,18,28,0,34,62,2,0,0,0,0,0,0,0,47,67>>.
<<Opts:8,MobIdLength:8,MobId:64,MobIdType:8,MgeType:8,SeqNum:16,Rest/binary>> = Packet.
It works just fine. Is there some subtlety in passing this to a function that I am missing? I have tried what I think is everything(except the right way). I tried setting the type and size. I also just tried
<<Rest/binary>> = Packet.
To no avail. Any help much appreciated.

The error you are getting when you run your code does not match your code. The error you are getting:
** exception error: no match of right hand side value ...
is a badmatch error and comes from an explicit = match where the pattern does not match the value from the RHS. There is no = in the code for rcv_loop/1. This implies that the loop you are running is not this code. So there are some questions to be asked:
When you have recompiled the module containing rcv_loop/1 have you restarted the loop so you run the new code? This is not done automagically.
Are you sure you are loading/running the code you think you are? I know this question sounds stupid but it is very easy, and not uncommon, to work on one version of the code and load another. You need to get the paths right.
The other things about mentioned about your code would not give this error. The calls to io:format/2 are wrong but would result in errors when you make the actual calls to io:format/2. Using the variable Socket as you do is not an error, it just means that you only want to receive UDP packets from just that socket.

EDIT : the first part of my answer was completely wrong so in order to not mislead, I deleted it.
Like spotted Alexey Kachayev io:format takes as second parameter a list, so :
packet_decoder(Packet)->
<<Opts:8,MobIdLength:8,MobId:64,MobIdType:8,MgeType:8,SeqNum:16,Rest/binary>> = Packet,
io:format("Options:~p~n",[Opts]),
io:format("MobIdLength:~p~n",[MobIdLength]),
io:format("MobId:~p~n",[MobId]),
io:format("MobIdType:~p~n",[MobIdType]),
io:format("MgeType:~p~n",[MgeType]),
io:format("SeqNum:~p~n",[SeqNum]).

I figured it out(kinda). I had been working on this in erlide in eclipse which had worked fine for all of the other parts of the. I tried compiling it from the erl shell and it worked fine. There must be some minor difference in the way eclipse is representing the source or the way it invokes the erlang compiler and shell. I will take it up with erlide.org. Thanks for the help!

Related

QtLua capture slider value change

I am trying to make a simple UI using qtlua, in which I want to capture the slider value everytime it changes. I tried to connect to the valueChanged() signal, but qlua gives me the following error:
cannot find source signal valueChanged()
The code snippet looks like this:
slide = (widget.sliderLight)
print(slide)
qt.connect(slide, 'valueChanged()',
function()
print('Value: ', slide.value)
end)
So just a test to print everytime the value changes. But I cannot get it working. The documentation for the qtlua doesn't have a class for qslider, so that's a dead end for me. And I couldn't find any examples for using qtlua with a slider that is connected to the valueChanged() signal. The only example I found was with the test.lua in the qtuiloader example, but that uses a timer, which I assume is pooled at regular interval. My aim is to hook this up to an image processing system, so it would be useful if I could tie it to when the value changes, rather than patch in with a timer and a check system. I am pretty new to qt, so must be missing something. Any and all help would be really appreciated!
Oh and I made sure I have tracking checkbox checked in the qtdesigner, to ensure that the signal is emitted.
Okay, so I dug around a little more in the documentation of QT for the valueChanged() slot. Turns out, the function signature has an int argument in it, so the Lua connect code was looking for a function signature without any arguments. Modifying the above code to the following works as expected:
slide = (widget.sliderLight)
print(slide)
qt.connect(slide, 'valueChanged(int)',
function(w)
print('Value: ', w)
end)
Declaring a function with the same signature also passes in the required value, which saves me an explicit value query.
Hopefully, this will be useful for someone someday.

ejabberd_router:route error in ejabberd module

I am trying to create a simple echo bot in ejabberd. I cam get the mod_echo working ok and i'm fairly certain I had my own version working at one point (debugging has played tricks with my head). I am getting the error below but i can't figure out what to do next to debug it. There seems to be an issue routing but not quite sure why. Any tips?
2016-03-31 16:49:38.350 [debug] <0.448.0>#ejabberd_router:do_route:324 route
from {jid,<<"user1">>,<<"alchemy.local">>,<<"alchemy">>,<<"user1">>,<<"alchemy.local">>,<<"alchemy">>}
to {jid,<<>>,<<"echo.alchemy.local">>,<<>>,<<>>,<<"echo.alchemy.local">>,<<>>}
packet {xmlel,<<"message">>,[{<<"xml:lang">>,<<"en">>},{<<"to">>,<<"echo.alchemy.local">>},{<<"id">>,<<"aacca">>}],[{xmlcdata,<<"\n">>},{xmlel,<<"subject">>,[],[]},{xmlcdata,<<"\n">>},{xmlel,<<"body">>,[],[{xmlcdata,<<"testme">>}]},{xmlcdata,<<"\n">>},{xmlel,<<"nick">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/nick">>}],[{xmlcdata,<<"user1">>}]},{xmlcdata,<<"\n">>}]}
2016-03-31 16:49:38.351 [error] <0.448.0>#ejabberd_router:route:77 {function_clause,[{mod_echobot,route,[{jid,<<"user1">>,<<"alchemy.local">>,<<"alchemy">>,<<"user1">>,<<"alchemy.local">>,<<"alchemy">>},{jid,<<>>,<<"echo.alchemy.local">>,<<>>,<<>>,<<"echo.alchemy.local">>,<<>>},{xmlel,<<"message">>,[{<<"xml:lang">>,<<"en">>},{<<"to">>,<<"echo.alchemy.local">>},{<<"id">>,<<"aacca">>}],[{xmlcdata,<<"\n">>},{xmlel,<<"subject">>,[],[]},{xmlcdata,<<"\n">>},{xmlel,<<"body">>,[],[{xmlcdata,<<"testme">>}]},{xmlcdata,<<"\n">>},{xmlel,<<"nick">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/nick">>}],[{xmlcdata,<<"user1">>}]},{xmlcdata,<<"\n">>}]}],[{file,"mod_echobot.erl"},{line,86}]},{ejabberd_router,route,3,[{file,"src/ejabberd_router.erl"},{line,75}]},{ejabberd_c2s,check_privacy_route,5,[{file,"src/ejabberd_c2s.erl"},{line,2121}]},{ejabberd_c2s,session_established2,2,[{file,"src/ejabberd_c2s.erl"},{line,1288}]},{p1_fsm,handle_msg,10,[{file,"src/p1_fsm.erl"},{line,582}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,237}]}]}
when processing: {{jid,<<"user1">>,<<"alchemy.local">>,<<"alchemy">>,<<"user1">>,<<"alchemy.local">>,<<"alchemy">>},{jid,<<>>,<<"echo.alchemy.local">>,<<>>,<<>>,<<"echo.alchemy.local">>,<<>>},{xmlel,<<"message">>,[{<<"xml:lang">>,<<"en">>},{<<"to">>,<<"echo.alchemy.local">>},{<<"id">>,<<"aacca">>}],[{xmlcdata,<<"\n">>},{xmlel,<<"subject">>,[],[]},{xmlcdata,<<"\n">>},{xmlel,<<"body">>,[],[{xmlcdata,<<"testme">>}]},{xmlcdata,<<"\n">>},{xmlel,<<"nick">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/nick">>}],[{xmlcdata,<<"user1">>}]},{xmlcdata,<<"\n">>}]}}
2016-03-31 16:50:16.356 [debug] <0.447.0>#ejabberd_receiver:process_data:282 Received XML on stream = <<"\n">>
It seems that in the code sample (which was from an older sample i found online) https://gist.github.com/stevenlivz/d666200595a23c42b2a662fef87bf281 i need to use <<"message">> in the clauses to actually match, whereas the sample code i used did not do that, using just "message" and so on. Also, also worth noting that xmlelement is now xmlel and so clauses also need to be updated. E.g.
route(From, To, {xmlel, <<"message">>, _, _} = Packet) ->

Unable to spawn process on another node in Erlang

When I try to create a new process on separate node using
Pid = spawn(mynode, mymodule, myfunction, [self()])
(myfunction/1 is exported), I get this error:
Error in process <0.10.0> on node 'no#de1' with exit value:
{undef,[{mymodule, myfunction, [<33.64.0>], []}]}
I tried to set -compile(export_all) flag, but assuming the additional braces in error log, this is not the case.
I don't know what causes the error and I have no clue what to do.
The error you get is saying “There is no module ‘mymodule’ and/or no function ‘mymodule:myfunction/1’”.
This means mymodule is not loaded in the code server of your separate node.
To load mymodule's code there you need something like this snippet or this function
Did you check that the module mymodule is in the path of no#de1?
When you spwan a process using spawn(mynode, mymodule, myfunction, [self()]), the VM needs to load the code before executing it.
If you use a high order function (a fun) in this way spawn(Node, Fun), then in is not more necessary to have the code in the path (but beware that any call to a function in the function definition need to be solved on the remote node)
go to no#de1 and run m(mymodule). It should clarify if the module is loadable and which functions does export.
also: check if the other node is reachable. Do a net_adm:ping on it.

What kind of types can be sent on an Erlang message?

Mainly I want to know if I can send a function in a message in a distributed Erlang setup.
On Machine 1:
F1 = Fun()-> hey end,
gen_server:call(on_other_machine,F1)
On Machine 2:
handler_call(Function,From,State) ->
{reply,Function(),State)
Does it make sense?
Here's an interesting article about "passing fun's to other Erlang nodes". To resume it briefly:
[...] As you might know, Erlang distribution
works by sending the binary encoding
of terms; and so sending a fun is also
essentially done by encoding it using
erlang:term_to_binary/1; passing the
resulting binary to another node, and
then decoding it again using
erlang:binary_to_term/1.[...]
This is pretty obvious
for most data types; but how does it
work for function objects?
When you encode a fun, what is encoded
is just a reference to the function,
not the function implementation.
[...]
[...]the definition of the function is not passed along; just exactly enough information to recreate the fun at an other node if the module is there.
[...] If the module containing the fun has not yet been loaded, and the target node is running in interactive mode; then the module is attempted loaded using the regular module loading mechanism (contained in the module error_handler); and then it tries to see if a fun with the given id is available in said module. However, this only happens lazily when you try to apply the function.
[...] If you never attempt to apply the function, then nothing bad happens. The fun can be passed to another node (which has the module/fun in question) and then everybody is happy.
Maybe the target node has a module loaded of said name, but perhaps in a different version; which would then be very likely to have a different MD5 checksum, then you get the error badfun if you try to apply it.
I would suggest you to read the whole article, cause it's extremely interesting.
You can send any valid Erlang term. Although you have to be careful when sending funs. Any fun referencing a function inside a module needs that module to exist on the target node to work:
(first#host)9> rpc:call(second#host, erlang, apply,
[fun io:format/1, ["Hey!~n"]]).
Hey!
ok
(first#host)10> mymodule:func("Hey!~n").
5
(first#host)11> rpc:call(second#host, erlang, apply,
[fun mymodule:func/1, ["Hey!~n"]]).
{badrpc,{'EXIT',{undef,[{mymodule,func,["Hey!~n"]},
{rpc,'-handle_call_call/6-fun-0-',5}]}}}
In this example, io exists on both nodes and it works to send a function from io as a fun. However, mymodule exists only on the first node and the fun generates an undef exception when called on the other node.
As for anonymous functions, it seems they can be sent and work as expected.
t1#localhost:
(t1#localhost)7> register(shell, self()).
true
(t1#localhost)10> A = me, receive Fun when is_function(Fun) -> Fun(A) end.
hello me you
ok
t2#localhost:
(t2#localhost)11> B = you.
you
(t2#localhost)12> Fn2 = fun (A) -> io:format("hello ~p ~p~n", [A, B]) end.
#Fun<erl_eval.6.54118792>
(t2#localhost)13> {shell, 't1#localhost'} ! Fn2.
I am adding coverage logic to an app built on riak-core, and the merge of results gathered can be tricky if anonymous functions cannot be used in messages.
Also check out riak_kv/src/riak_kv_coverage_filter.erl
riak_kv might be using it to filter result, I guess.

Two quick consecutive calls to wf:insert_bottom end up in the reverse order

Using Nitrogen, the Erlang web framework, I have the following method that receives messages and adds them to the bottom of an html element:
receive_messages() ->
receive
Message ->
io:format("~p received ~p", [self(), Message]),
wf:insert_bottom(messages, [#p{}, #span { text=io_lib:format("~p", [Message]) }])
end,
wf:comet_flush(),
receive_messages().
It is set as the usual way for comet:
wf:comet(fun() -> receive_messages() end)
It receives two messages very quickly:
<0.907.0> received {starting_chat,<0.905.0>}
<0.907.0> received {connected_to,<0.902.0>}
This is what I see in the HTML:
{connected_to, <0.902.0>}
{starting_chat, <0.905.0>}
Somehow, they ended in the reverse order.
I've started adding timer:sleep() calls to this method. With 50 milliseconds, they are in the correct order, with 20 they are not. When they are in the incorrect order they seem to be always in the incorrect order, it seems very deterministic.
Any ideas why? Is this a bug? Any ideas what should I do to get them in the correct order other than sleeping?
Also asked on the mailing list, in case there's more info there.
wf_comet.erl has a "strange" reverse call after applying inner_collect_content. My guess is that inner_collect_content used to be tail-recursive sometime ago.
If you apply the timeout, your messages are collected in different loops, one-by-one, so the order is not reversed anymore.
There seems to be a commit fixing this on another repository:
http://github.com/gersh/nitrogen/commit/a8bfcb23d003e68f7394a0455285beeb0fbf9b09

Resources