Erlang - extract tuple from list of tuples - erlang

Hi first of all I'm a beginner regarding Erlang,
I'm trying to extract a tuple from a list of tuples and assign it to a variable.
Consider this dataset.
[{0,25075,-2},{0,0,-2},{0,376100,-4}]
For example, I want to assign {0,25075,-2} to something like Var1 and so on.
I've tried the following in the shell for testing;
Tuples = [{0,25075,-2},{0,0,-2},{0,376100,-4}].
{Var1, Var2, Var3} = Tuples.
But I get this error;
ฐ** exception error: no match of right hand side value
[{0,25075,-2},{0,0,-2},{0,376100,-4}]
Any help would be appreciated, thanks.

In the shell, if you have already assigned a value to a variable then you must clear the variable before reusing it. Use the command f(). to clear all current variables, or f(Var1). to just clear Var1.
Secondly, your syntax is wrong. It should be:
1> Tuples = [{0,25075,-2},{0,0,-2},{0,376100,-4}].
[{0,25075,-2},{0,0,-2},{0,376100,-4}]
2> [Var1, Var2, Var3] = Tuples.
[{0,25075,-2},{0,0,-2},{0,376100,-4}]
3> Var1.
{0,25075,-2}
4> Var2.
{0,0,-2}
5> Var3.
{0,376100,-4}
6> Var1 = "something else".
** exception error: no match of right hand side value "something else"
7> f(Var1).
ok
8> Var1 = "something else".
"something else"
9> Var1.
"something else"
You will not do assignments like this over lists very often, though, typically you will iterate and/or use list operations.

Related

What does (_,[]) mean?

I was given a question which was:
given a number N in the first argument selects only numbers greater than N in the list, so that
greater(2,[2,13,1,4,13]) = [13,4,13]
This was the solution provided:
member(_,[]) -> false;
member(H,[H|_]) -> true;
member(N,[_,T]) -> member(N,T).
I don't understand what "_" means. I understand it has something to do with pattern matching but I don't understand it completely. Could someone please explain this to me
This was the solution provided:
I think you are confused: the name of the solution function isn't even the same as the name of the function in the question. The member/2 function returns true when the first argument is an element of the list provided as the second argument, and it returns false otherwise.
I don't understand what "_" means. I understand it has something to do with pattern matching but I don't understand it completely. Could someone please explain this to me
_ is a variable name, and like any variable it will match anything. Here are some examples of pattern matching:
35> f(). %"Forget" or erase all variable bindings
ok
45> {X, Y} = {10, 20}.
{10,20}
46> X.
10
47> Y.
20
48> {X, Y} = {30, 20}.
** exception error: no match of right hand side value {30,
20}
Now why didn't line 48 match? X was already bound to 10 and Y to 20, so erlang replaces those variables with their values, which gives you:
48> {10, 20} = {30, 20}.
...and those tuples don't match.
Now lets try it with a variable named _:
49> f().
ok
50> {_, Y} = {10, 20}.
{10,20}
51> Y.
20
52> {_, Y} = {30, 20}.
{30,20}
53>
As you can see, the variable _ sort of works like the variable X, but notice that there is no error on line 52, like there was on line 48. That's because the _ variable works a little differently than X:
53> _.
* 1: variable '_' is unbound
In other words, _ is a variable name, so it will initially match anything, but unlike X, the variable _ is never bound/assigned a value, so you can use it over and over again without error to match anything.
The _ variable is also known as a don't care variable because you don't care what that variable matches because it's not important to your code, and you don't need to use its value.
Let's apply those lessons to your solution. This line:
member(N,[_,T]) -> member(N,T).
recursively calls the member function, namely member(N, T). And, the following function clause:
member(_,[]) -> false;
will match the function call member(N, T) whenever T is an empty list--no matter what the value of N is. In other words, once the given number N has not matched any element in the list, i.e. when the list is empty so there are no more elements to check, then the function clause:
member(_,[]) -> false;
will match and return false.
You could rewrite that function clause like this:
member(N, []) -> false;
but erlang will warn you that N is an unused variable in the body of the function, which is a way of saying: "Are you sure you didn't make a mistake in your function definition? You defined a variable named N, but then you didn't use it in the body of the function!" The way you tell erlang that the function definition is indeed correct is to change the variable name N to _ (or _N).
It means a variable you don't care to name. If you are never going to use a variable inside the function you can just use underscore.
% if the list is empty, it has no members
member(_, []) -> false.
% if the element I am searching for is the head of the list, it is a member
member(H,[H|_]) -> true.
% if the elem I am searching for is not the head of the list, and the list
% is not empty, lets recursively go look at the tail of the list to see if
% it is present there
member(H,[_|T]) -> member(H,T).
the above is pseudo code for what is happening. You can also have multiple '_' unnamed variables.
According to Documentation:
The anonymous variable is denoted by underscore (_) and can be used when a variable is required but its value can be ignored.
Example:
[H, _] = [1,2] % H will be 1
Also documentation says that:
Variables starting with underscore (_), for example, _Height, are normal variables, not anonymous. They are however ignored by the compiler in the sense that they do not generate any warnings for unused variables.
Sorry if this is repetitive...
What does (_,[]) mean?
That means (1) two parameters, (2) the first one matches anything and everything, yet I don't care about it (you're telling Erlang to just forget about its value via the underscore) and (3) the second parameter is an empty list.
Given that Erlang binds or matches values with variables (depending on the particular case), here you're basically looking to a match (like a conditional statement) of the second parameter with an empty list. If that match happens, the statement returns false. Otherwise, it tries to match the two parameters of the function call with one of the other two statements below it.

erlang, ejabberd, how to deal with [{text, <<>>, <<"hello">>}] formats

So I got a hook in my code that says if an offline message is received, it will start up this function.
offline_msg_received(From, To, Packet) ->
The Packet has code looking like this:
{message,<<"purple2d957668">>,chat,<<>>,undefined,{jid,<<"admin">>,<<"localhost">>,<<"5280">>,<<"admin">>,<<"localhost">>,<<"5280">>},[],[{text,<<>>,<<"Hello">>}],undefined,[{xmlel,<<"active">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/chatstates">>}],[]}],#{}}
What I wanted out of this is the part containing my message. Which is:
[{text,<<>>,<<"Hello">>}]
I could get this part out with a pattern matching against the whole package variable. However, when I tried a pattern matching with my message, it says bad argument. I know that if I specify a variable with just
{text,<<>>,<<"Hello">>}
then I can pattern match against that. From my understanding, seeing [ ] around something means it is a list, or a string.
I can show some of the code here.
{P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11} = Packet, %% P8 is the message I want.
?INFO_MSG("----------------------P8: ~p~n", P8), %% This shows {text,<<>>,<<"Hello">>}
{A, B, C} = P8, %% This gives me a badmatch error.
Now, if I were to instead do this manually in the code shell:
{text,<<>>,<<"Hello">>} = P8,
{A, B, C} = P8,
Then the code works, and puts <<"Hello">> in the C variable.
My guess is that the [ ] around it in the "Package" variable has something to do with my badmatch error, but for some reason those symbols don't appear when I print out P8. Does anyone have a good suggestion why it doesn't work? I am guessing it has something to do with the hidden [ ], since otherwise it looks identical to my shell code test.
Thanks. This is my first time asking questions here, so I hope I didn't do anything wrong.
The reason you're not seeing the square brackets around the value in your INFO_MSG call is that INFO_MSG expects a list of values, not just a single value. In the code above it happens to work out, since the format string only contains a single directive, and the value is a list of one element, so that's why the brackets are silently stripped out.
The INFO_MSG macro works the same as io:format, so you could try this out in the shell:
%% two arguments
io:format("~p ~p\n", [foo, bar]).
%% one argument - we still need square brackets
io:format("~p\n", [foo]).
You're doing this the hard way :) message and text are records defined in xmpp_codec.hrl. If you don't have the record definitions loaded in the shell, records look like a tuple with lots of elements, but if you load the record definitions, your message looks like this instead:
1> rr("include/xmpp_codec.hrl").
[address,addresses,adhoc_actions,adhoc_command,adhoc_note,
bind,block,block_list,bob_data,bookmark_conference,
bookmark_storage,bookmark_url,bytestreams,caps,
carbons_disable,carbons_enable,carbons_private,
carbons_received,carbons_sent,chatstate,client_id,compress,
compress_failure,compressed,compression,csi,db_feature,
db_result,db_verify|...]
2> {message,<<"purple2d957668">>,chat,<<>>,undefined,{jid,<<"admin">>,<<"localhost">>,<<"5280">>,<<"admin">>,<<"localhost">>,<<"5280">>},[],[{text,<<>>,<<"Hello">>}],undefined,[{xmlel,<<"active">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/chatstates">>}],[]}],#{}}.
#message{id = <<"purple2d957668">>,type = chat,lang = <<>>,
from = undefined,
to = {jid,<<"admin">>,<<"localhost">>,<<"5280">>,
<<"admin">>,<<"localhost">>,<<"5280">>},
subject = [],
body = [#text{lang = <<>>,data = <<"Hello">>}],
thread = undefined,
sub_els = [{xmlel,<<"active">>,
[{<<"xmlns">>,
<<"http://jabber.org/protocol/chatstates">>}],
[]}],
meta = #{}}
The data you are looking for is in the body field.
Let's assign this record to the variable M and extract the body field:
4> Body = M#message.body.
[#text{lang = <<>>,data = <<"Hello">>}]
So that's a list containing one text record. Let's extract the data field from that:
6> [#text{data = Data}] = Body.
[#text{lang = <<>>,data = <<"Hello">>}]
7> Data.
<<"Hello">>
That's how it works in the shell - load the record definitions with the rr function. When writing a module that uses record definitions, you'd need to include the hrl file:
-include_lib("xmpp/include/xmpp_codec.hrl").
The -include_lib directory will look for the xmpp application on the load path, and search for the file xmpp_codec.hrl inside its include directory. You may need to specify the code path to the compiler, something like erlc -pa path/to/xmpp/ebin my_module.erl - note that the ebin directory inside the application should be on the code path.

Erlang list of tuples jsx:encode error

I want to create a List of tuples in json format with jsx:encode, which is returning error:
io:format("Mylist After reverse ==========: ~n~p~n",[Mylist]),
FinalReading = lists:map(
fun(X) ->
jsx:encode([X])
end, Mylist),
Mylist is printed as follows:
[{{<<"name">>,<<"Batman">>},{<<"steps">>,1033},{<<"distance">>,830}},
{{<<"name">>,<<"Superman">>},{<<"steps">>,641},{<<"distance">>,520}}]
I'm getting this error:
09:49:24.048 [error] ** Boss Service Handler myproj_priv_mylib_websocket terminating in handle_incoming/4
for the reason error:badarg
ServiceUrl: "/websocket/mylib"
WebSocketId: <0.336.0>
SessionId : <<"a4f60118091309990af7c89c9a1acb49ee3bb08d">>
Message : <<"admin#mydomain.com:z3CMLU9jDTYdiAacNiJrMIkdp4lTf6sb">>
State : []
** Stacktrace: [{jsx_parser,value,4,[{file,"src/jsx_parser.erl"},{line,125}]},{lists,map,2,[{file,"lists.erl"},{line,1237}]},{myproj_priv_mylib_websocket,handle_incoming,5,[{file,"..."},{line,130}]},{boss_service_worker,handle_cast,2,[{file,"src/boss/boss_service_worker.erl"},{line,173}]},{gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,599}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]
It would be great if someone points out the correct code.
Thanking all in advance.
You'll have to convert the top level tuples to lists using erlang:tuple_to_list/1 and lists:map/2 so that jsx can correctly encode them to a JSON Array.
1> List = [{{<<"name">>,<<"Batman">>},{<<"steps">>,1033},{<<"distance">>,830}},
1> {{<<"name">>,<<"Superman">>},{<<"steps">>,641},{<<"distance">>,520}}].
[{{<<"name">>,<<"Batman">>},
{<<"steps">>,1033},
{<<"distance">>,830}},
{{<<"name">>,<<"Superman">>},
{<<"steps">>,641},
{<<"distance">>,520}}]
2> List2 = lists:map(fun erlang:tuple_to_list/1, List).
[[{<<"name">>,<<"Batman">>},
{<<"steps">>,1033},
{<<"distance">>,830}],
[{<<"name">>,<<"Superman">>},
{<<"steps">>,641},
{<<"distance">>,520}]]
3> io:format("~s~n", [jsx:encode(List2)]).
[{"name":"Batman","steps":1033,"distance":830},{"name":"Superman","steps":641,"distance":520}]
I'm very much a newbie to Erlang, so not sure if I've the right to judge, but my feeling is that it would be good to hide the need to convert the tuple to list in jsx:encode.
If
[{a,<<"a">>}, {b,<<"b">>}].
becomes
{
"a" : "a",
"b" : "b"
}
I believe the same should work as well for this syntax
{{a,<<"a">>}, {b,<<"b">>}}.
This last syntax brings more information (it reflects an ordering which I can count on, within the code, for pattern matching).
I usually try to convert my JSON into a tuple for which I know the ordering, so that I can play with pattern matching instead of using keyfind and friends. But because the above syntax does not work, I have to wrap jsx:encode(tuple_to_list()) to automatically manage "PropTuples".
Am I completely misunderstanding it? Is there a more decent way to represent/treat/manipulate JSON in Erlang?

erlang : placeholder in tuple (or list)

I'd like to tidy my Eralng code, I found there're lots of issue following:
A = {Tid, _Tv0, _Tv1, Tv2, Tv3}
Is there any way to clean the code like to be: A = {Tid, SomewayReplace(4)} ???
Update1:
like #Pascal example, Is there any way to simple the code A = {T, _, _, _, _, _} like to be A = {T, SomewayReplace(4)} to replace that 4 symbol _ ???
update2
in real project, if some record include many element, I found it force me to repeat writing the symbol _, so I wonder if there is any way to simple it???
Writting A = Something means that you try to match A with Something or if A is unbound, assign Something to A. In anycase, Something must be defined.
You can find some shortcut in writting. For example, if you want to assign the result of a funtion to A, verify that the result is a tuple of 5 elements and assign the first element to T, the you can write:
A = {T,_,_,_,_} = f(Param).
The meaning of _T is exactly the same as any variable. It just says to th compiler to not issue a warning if this variable is not used in the code. It is frequent in pattern matching when you want to ignore the value of a variable but still keep trace of its meaning.
[edit]
It is not possible to write {T, SomewayReplace(4)}, but you may use records. A record is a tagged tuple (first element is the atom that identify this record. It is not shorter than placeholder for small tuples, but it is clearer, you don't need to remember the location of the information in your tuple, and it is easier to modify your code when you need to add a new element in a tuple. The syntax will be
-record(mytuple,{field1,...,fieldx,...}.
...
A = #mytuple{fieldx = T} = f(Param).
waerning: Records are managed by the compiler, so everything must be known at build time (#mytuple{Fieldx = T} is illegal, Fieldx cannot be a variable).
Why not use a record? Then you only match the fields you want to extract. As a by-effect, you make the code easier to debug, since you are forced to name the tuple by having a atom first.

Erlang MapReduce on Riak database giving exception

I am going through the tutorials of riak and Erlang, I have stored data in riak by the riak-erlang-client and i did the following:
1> {ok,Pid} = riakc_pb_socket:start_link("127.0.0.1", 8087).
{ok,<0.34.0>}
2> Val1 = [1,2,3].
[1,2,3]
3> MyBucket = <<"numbers">>.
<<"numbers">>
4> Obj1 = riakc_obj:new(MyBucket,<<"ott">>,Val1).
5> riakc_pb_socket:put(Pid,Obj1).
ok
6> {ok, Fetched} = riakc_pb_socket:get(Pid,MyBucket,<<"ott">>).
{ok,{riakc_obj,<<"numbers">>,<<"ott">>,
<<107,206,97,96,96,96,204,96,202,5,82,28,202,156,255,126,
6,251,159,184,148,193,148,...>>,
[{{dict,3,16,16,8,80,48,
{[],[],[],[],[],[],[],[],[],[],[],[],...},
{{[],[],[],[],[],[],[],[],[],[],...}}},
<<131,107,0,3,1,2,3>>}],
undefined,undefined}}
7> Val1 == binary_to_term(riakc_obj:get_value(Fetched)).
true
8> binary_to_term(riakc_obj:get_value(Fetched)).
[1,2,3]
Now everything was fine , i want to extract the values from the list [1,2,3] that where only divisible by 2 from a mapreduce through erlang.
for that i have done the following,
9>Res = fun(Fetched,none)-> [X || X <- binary_to_term(riakc_obj:get_value(Fetched)), X rem 2 == 0] end.
I don't know exactly about what should write in the function parameters,as i am new to erlang and riak, so please correct me if am wrong.
Now when i going for mapreduce i have written this,
10>{ok , [{X}]} = riakc_pb_socket:mapred(Pid,[{<<"numbers">>,<<"ott">>}],[{map,{qfun,Res},none,true}]).
It was throwing the below exception..please suggest me a good way to understand what's going on and how to run mapreduce.
** exception exit: {noproc,{gen_server,call,
[<0.34.0>,
{req,{rpbmapredreq,<<131,108,0,0,0,3,104,2,100,0,6,105,
110,112,117,116,115,108,...>>,
<<"application/x-erlang-binary">>},
60100,
{132578423,<0.49.0>}},
infinity]}}
in function gen_server:call/3 (gen_server.erl, line 188)
in call from riakc_pb_socket:mapred/5 (src/riakc_pb_socket.erl, line 643)
Please,help me and suggest me, i hjave followed the links but i am not getting clearly that how to write on my own for a mapreduce so please guide me..it will help me.
You are getting the noproc error because you are passing an arity-2 function. The map phase function should be arity-3. Also, specifying none in the function header will cause that clause to only be executed when the corresponding argument explicitly matches, use _ in place of arguments you don't care about, like:
Res = fun(Fetched,_,_)-> [X || X <- binary_to_term(riakc_obj:get_value(Fetched)), X rem 2 == 0] end.

Resources