Erlang printing hex instead of integer - erlang

I have been trying to fix a problem for hours now, very new to erlang
lists:sublist([6,9,15,24,39,6,96],7,1).
I want this to print "100" instead of "d"
what I am i doing wrong here?

The shell is going to try to print strings as strings whenever it would be legal. That means lists of integers that happen to all be valid characters will be printed as characters, and lists that contain other things will be printed as lists:
1> [65,66,67].
"ABC"
2> [3,65,66,67].
[3,65,66,67]
But notice that I did not actually call any output functions. That was just the shell's convenience operation of implicitly echoing whatever a returned value was so you, as a programmer, can inspect it.
If I want to explicitly call an output function I should use a format string that specifies the nature of the values to be interpolated:
3> io:format("This is a list: ~tw~n", [List]).
This is a list: [65,66,67]
ok
4> io:format("This is a list rendered as an implied string: ~tp~n", [List]).
This is a list rendered as an implied string: "ABC"
ok
5> io:format("This is a string: ~ts~n", [List]).
This is a string: ABC
ok
Note the additional atom ok after each print. That is because the return value from io:format/2 is ok. So we are getting the explicit output from format/2 and then seeing its return value.
The io module doc page has the gritty details: http://erlang.org/doc/man/io.html#format-1
Back to your example...
6> lists:sublist([6,9,15,24,39,6,96],7,1).
"`"
7> io:format("~tw~n", [lists:sublist([6,9,15,24,39,6,96],7,1)]).
[96]
ok
Addendum
There is a setting called shell:strings/1 that tells the shell to turn string formatting on and off:
1> [65,66,67].
"ABC"
2> shell:strings(false).
true
3> [65,66,67].
[65,66,67]
4> <<65,66,67>>.
<<65,66,67>>
5> shell:strings(true).
false
6> <<65,66,67>>.
<<"ABC">>
But I don't mess with this setting ever anymore for a few reasons:
It is almost never worth the effort to remember this detail of the shell (convenience output from the shell is mostly useful for discovering return value structures, not specific values held by those structures -- and when you want that data you usually want strings printed as strings anyway).
It can cause surprising shell output in any case where you really are dealing with strings.
This is almost never the behavior you actually want.
When dealing with real programs you will need actual output functions using io or io_lib modules, and developing habits around format strings is much more useful than worrying over convenience output from the shell.

Related

Converting a tuple to a string in erlang language

Tuple={<<"jid">>,Member},
Tuple_in_string=lists:flatten(io_lib:format("~p", [Tuple])),
it gives output as:
"{<<\"jid\">>,\"sdfs\"}"
But i want this output without these slashes like
"{<<"jid">>,Member}"
Any pointers?
I have tried all the answers but at the end with io:format("\"~s\"~n", [Tuple_in_string]). what am geeting is "{<<"jid">>,Member}" but it is not a string.it is a atom.I need string on which i can apply concat operation.Any pointers?
You can print it like this:
io:format("\"~s\"~n", [Tuple_in_string]).
It prints:
"{<<"jid">>,"sdfs"}"
The \ are here to denote that the following " is part of the string and not a string delimiter. they do not exist in the string itself. They appear because you use the pretty print format ~p. If you use the string format ~s they wont appear in the display.
1> io:format("~p~n",["a \"string\""]).
"a \"string\""
ok
2> io:format("~s~n",["a \"string\""]).
a "string"
ok
3> length("a \"string\""). % is 10 and not 12
10
Firstly, you don't need to flatten the list here:
Tuple_in_string=lists:flatten(io_lib:format("~p", [Tuple])),
Erlang has the concept of iodata(), which means that printable things can be in nested lists and most functions can handle them, so you should leave only:
Tuple_in_string = io_lib:format("~p", [Tuple]),
Secondly, when you use ~p, you tell Erlang to print the term in such way, that it can be copied and pasted into console. That is why all double quotes are escaped \". Use ~s, which means "treat as string".
1> 38> Tuple = {<<"jid">>,"asdf"}.
{<<"jid">>,"asdf"}
2> IODATA = io_lib:format("~p", [Tuple]).
[[123,[[60,60,"\"jid\"",62,62],44,"\"asdf\""],125]]
3> io:format("~s~n", [IODATA]).
{<<"jid">>,"asdf"}
ok
L = Packet_in_tuple_form={xmlel,<<"message">>,[{<<"id">>,<<"rkX6Q-8">>},{<<"to">>,<<"multicast.devlab">>}],[{xmlel,<<"body">>,[],[{xmlcdata,"Hello"}]},{xmlel,<<"addresses">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/address">>}],[{xmlel,<<"address">>,[{<<"type">>,<<"to">>},"{<<\"jid\">>,\"sds\"}",{<<"desc">>,"Description"}],[]}]}]}.
Gives me:
{xmlel,<<"message">>,
[{<<"id">>,<<"rkX6Q-8">>},{<<"to">>,<<"multicast.devlab">>}],
[{xmlel,<<"body">>,[],[{xmlcdata,"Hello"}]},
{xmlel,<<"addresses">>,
[{<<"xmlns">>,<<"http://jabber.org/protocol/address">>}],
[{xmlel,<<"address">>,
[{<<"type">>,<<"to">>},
"{<<\"jid\">>,\"sds\"}",
{<<"desc">>,"Description"}],
[]}]}]}
The \ in the address field are escape characters.
You can verify the same by checking the length of string.

Simple explanation of Erlang atom

I am learning Erlang and stuck trying to understand the concept of atoms. I know Python: What is a good explanation of these "atoms" in simple terms, or analogously with Python. So far, my understanding is that the type is like a string but without string operations?
Docs say that:
An atom is a literal, a constant with name.
Sometimes you have couple of options, that you would like to choose from. In C for example, you have enum:
enum Weekday { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday };
In C, it is really an integer, but you can use it in code as one of options. Atoms in Erlang are very useful in pattern matching. Lets consider very simple server:
loop() ->
receive
{request_type_1, Request} ->
handle_request_1(Request),
loop();
{request_type_2, Request} ->
handle_request_2(Request),
loop();
{stop, Reason} ->
{ok, Reason};
_ ->
{error, bad_request}
end.
Your server receives messages, that are two element tuples and uses atoms to differentiate between different types of requests: request_type_1, request_type_2 and stop. It is called pattern matching.
Server also uses atoms as return values. ok atom means, that everything went ok. _ matches everything, so in case, that simple server receives something unexpected, it quits with tuple {error, Reason}, where the reason is also atom bad_request.
Boolean values true and false are also atoms. You can build logical functions using function clauses like this:
and(true, true) ->
true;
and(_, _) ->
false.
or(false, false) ->
false;
or(_, _) ->
true.
(It is a little bit oversimplified, because you can call it like this: or(atom1, atom2) and it will return true, but it is only for illustration.)
Module names in Erlang are also atoms, so you can bind module name to variable and call it, for example type this in Erlang shell:
io:format("asdf").
Variable = io.
Variable:format("asdf").
You should not use atoms as strings, because they are not garbage collected. If you start creating them dynamically, you can run out of memory. They should be only used, when there is fixed amount of options, that you type in code by hand. Of course, you can use the same atom as many times as you want, because it always points to the same point in memory (an atom table).
They are better than C enums, because the value is known at runtime. So while debugging C code, you would see 1 instead of Tuesday in debugger. Using atoms doesn't have that disadvantage, you will see tuesday in your both in your code and Erlang shell.
Also, they're often used to tag a tuple, for descriptiveness. For example:
{age, 42}
Rather than just
42
Atom is a literal constant. Has no value but can be used as a value. Examples are: true, false, undefined. If you want to use it as a string, you need to apply atom_to_list(atom) to get a string (list) to work with. Module names are also atoms.
Take a look at http://www.erlang.org/doc/reference_manual/data_types.html

Erlang matchspecs with tuple comparison

I want to use erlang datetime values in the standard format {{Y,M,D},{H,Min,Sec}} in a MNESIA table for logging purposes and be able to select log entries by comparing with constant start and end time tuples.
It seems that the matchspec guard compiler somehow confuses tuple values with guard sub-expressions. Evaluating ets:match_spec_compile(MatchSpec) fails for
MatchSpec = [
{
{'_','$1','$2'}
,
[
{'==','$2',{1,2}}
]
,
['$_']
}
]
but succeeds when I compare $2 with any non-tuple value.
Is there a restriction that match guards cannot compare tuple values?
I believe the answer is to use double braces when using tuples (see Variables and Literals section of http://www.erlang.org/doc/apps/erts/match_spec.html#id69408). So to use a tuple in a matchspec expression, surround that tuple with braces, as in,
{'==','$2',{{1,2}}}
So, if I understand your example correctly, you would have
22> M=[{{'_','$1','$2'},[{'==','$2',{{1,2}}}],['$_']}].
[{{'_','$1','$2'},[{'==','$2',{{1,2}}}],['$_']}]
23> ets:match_spec_run([{1,1,{1,2}}],ets:match_spec_compile(M)).
[{1,1,{1,2}}]
24> ets:match_spec_run([{1,1,{2,2}}],ets:match_spec_compile(M)).
[]
EDIT: (sorry to edit your answer but this was the easiest way to get my comment in a readable form)
Yes, this is how it must be done. An easier way to get the match-spec is to use the (pseudo) function ets:fun2ms/1 which takes a literal fun as an argument and returns the match-spec. So
10> ets:fun2ms(fun ({A,B,C}=X) when C == {1,2} -> X end).
[{{'$1','$2','$3'},[{'==','$3',{{1,2}}}],['$_']}]
The shell recognises ets:fun2ms/1. For more information see ETS documentation. Mnesia uses the same match-specs as ETS.

Erlang - io:format 's result / (formatting with io_lib:format/2)

I'm trying to get the result of the output of io:format/1.
I know that there's a similar function in io_lib, io_lib:format/2, but the output is different. In fact, it doesn't do anything at all.
If I try to bound io:format, ok is bounded, and the formatted string is written out to the console.
So my question is, how can I get the same output with io_lib:format/2?
Or how can I bound the formatted string to a variable?
1> A = io:get_line('> ').
> "test".
"\"test\".\n"
2> io:format(A).
"test".
ok
3> B = io_lib:format(A, []).
"\"test\".\n"
4> B.
"\"test\".\n"
5> C = io:format(A).
"test".
ok
6> C.
ok
io_lib:format is not an output function the way io:format is. Instead io_lib:format only returns the value, but does not output it.
The result of io:format that you see as "test." is the rendered version as sent to the terminal (including the newline) , then it returns ok. Conversely, the return value of io_lib:format that you see as "\"test\".\n" is simply the erlang shell's representation of the same string, with the quotes and newline escaped, and surrounded by its own quotes.
io_lib:format is more commonly used for inserting values into the strings (similar to C's printf functions). For example, doing something like
NewString = io_lib:format("The string entered was ~s I hope you like it",[A])
The value of NewString would be
The string entered was "test".
I hope you like it
For which the Erlang Shell's representation would be:
"The string entered was \"test\".\n I hope you like it"
If all you want to do is output the value you just entered, then io:format is sufficient for your needs.

Can I disable printing lists of small integers as strings in Erlang shell?

The Erlang shell "guesses" whether a given list is a printable string and prints it that way for convenience. Can this "convenience" be disabled?
I don't know if it's possible to change the default behavior of the shell, but you can at least format your output correctly, using io:format.
Here is an example:
1> io:format("~p~n", [[65, 66, 67]]).
"ABC"
ok
2> io:format("~w~n", [[65, 66, 67]]).
[65,66,67]
ok
And since the shell is only for experimenting / maintenance, io:format() should be at least enough for your real application. Maybe you should also consider to write your own format/print method, e.g. formatPerson() or something like that, which formats everything nicely.
You can disable such behavior with shell:strings/1 function starting with Erlang R16B.
Just remember that this is option global to all node shells, and it might be wise to set it back after finishing playing is shell in longer living nodes.
I tend to do it by prepending an atom to my list in the shell.
for example:
Eshell V5.7.4 (abort with ^G)
1> [65,66,67].
"ABC"
2> [a|[65,66,67]].
[a,65,66,67]
could also be [a,65,66,67], of course. but [a|fun_that_returns_a_list()] will print "the right thing(ish) most of the time"
As of Erlang/OTP R16B, you can use the function shell:strings/1 to turn this on or off. Note that it also affects printing of things that are actually meant to be strings, such as "foo" in the following example:
1> {[8,9,10], "foo"}.
{"\b\t\n","foo"}
2> shell:strings(false).
true
3> {[8,9,10], "foo"}.
{[8,9,10],[102,111,111]}
No, there is no way to disable it. The best alternative I find is to either explicitly print out the value in the query (with io:format) or after the fact do: io:format("~w\n", [v(-1)]).
I don't think you can prevent it.
Prepending an atom seems like a kludge - it does alter your original string.
I typically use lists:flatten(String) to force it to a string - especially the returnvalue of io_lib:format() does not always print as a string. Using lists:flatten() on it makes it one.
I use the following "C-style":
sprintf(Format) ->
sprintf(Format, []).
sprintf(Format, Args) ->
lists:flatten(io_lib:format(Format, Args)).
The problem is that the string is not a type in Erlang. A string is just a list of integers, so there's no way for the shell to distinguish a printable string from a generic list. Don't know if this answer to your question.

Resources