How to store tuple and its size in a file in erlang? - erlang

I have created a gen_server that should receive a tuple sent from the erlang shell and write it to a file along with the tuple size.
Example: the input received is {"A","B","C","D"}, and it should be written to a file as:
{"A","B","C","D"};4
and so on. The gen_server should also receive new inputs and store them in a txt file each on a new line.
I have tried but my code is not generating the required output. Assume I have written basic gen_server code with start_link, init, handle_call, handle_cast, handle_info, terminate and code_change.

Try this:
go() ->
Tuple = {"A", "B", "C", "D"},
Length = tuple_size(Tuple),
{ok, TupleFile} = file:open("tuples.txt", [append]),
file:write(TupleFile,
io_lib:format("~p;~w~n", [Tuple, Length])
),
file:close(TupleFile).
io_lib:format() is like io:format() except instead of writing the string to the shell, io_lib:format() returns the string.
In the shell:
1> c(a).
a.erl:2:2: Warning: export_all flag enabled - all functions will be exported
% 2| -compile(export_all).
% | ^
{ok,a}
2> a:go().
ok
3>
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
(l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
~/erlang_programs% cat tuples.txt
{"A","B","C","D"};4

Related

Why does pattern matching on this string in erlang result in a "string" for the tail and an ascii value for the list?

I was trying to write a pattern matched function in erlang like:
to_end("A") -> "Z".
The whole idea is to transform a string such as "ABC" into something different such as "ZYX" using pattern matched functions. It looks like a string is represented as a list under the hood...
I was depending on the fact that pattern matching on a "string" in erlang would result in individual string characters. But I find this:
21> F="ABC".
22> F.
"ABC"
23> [H | T]=F.
"ABC"
24> H.
65
25> T.
"BC"
Why does the head of this type of pattern matching on list always result in an ASCII value and the tail result in letters? Is there a better way to pattern match against a "list of string"?
In Erlang, strings are just a list of ascii values. It also displays lists of integers, where every integer is a printable ascii code, as strings. So [48, 49] would print out "01" since 48 corresponds to 0 and 49 to 1. Since you have the string "ABC", this is the same as [65 | [66 | [67]]], and [66, 67] will display as "BC".
If you want to write a function to pattern match on characters, you should use the character literal syntax, which is $ followed by the character. So you would write
to_end($A) -> $Z;
to_end($B) -> $Y;
to_end($C) -> $X;
...
to_end($Z) -> $A.
instead of to_end("A") -> "Z" which is the same as to_end([65]) -> [90].
Why does the head of this type of pattern matching on list always
result in an ASCII value and the tail result in letters?
In erlang, the string "ABC" is a shorthand notation for the list [65,66,67]. The head of that list is 65, and the tail of that list is the list [66,67], which the shell happens to display as "BC". Whaa??!
The shell pretty much sucks when displaying strings/lists: sometimes the shell displays a list and sometimes the shell displays a double quoted string:
2> [0, 65, 66, 67].
[0,65,66,67]
3> [65, 66, 67].
"ABC"
4>
...which is just plain dumb. Every beginning and intermediate erlang programmer gets confused by that at some point.
Just remember: when the shell displays a double quoted string, it should really be displaying a list whose elements are the character codes of each character in the double quoted string. The fact that the shell displays a double quoted string is a TERRIBLE ??feature?? of erlang, and it makes it hard to decipher what is going on in a lot of situations. You have to mentally say to yourself, "That string I'm seeing in the shell is really the list ..."
That fact that the shell displays double quoted strings for some lists really sucks when you want to display, say, a list of a person's test scores: [88, 97, 92, 70] and the shell outputs: "Xa\\F". You can use the io:format() method to get around that:
6> io:format("~w~n", [[88,97,92,70]]).
[88,97,92,70]
ok
But, if you just want to momentarily see the actual list of integers that the shell is displaying as a string, a quick and dirty method is to add the integer 0 to the head of the list:
7> Scores = [88,97,92,70].
"Xa\\F"
Huh?!!
8> [0|Scores].
[0,88,97,92,70]
Oh, okay.
The whole idea is to transform a string such as "ABC" into something
different such as "ZYX" using pattern matched functions.
Because a string is shorthand for a list of integers, you can change those integers by using addition:
-module(my).
-compile(export_all).
cipher([]) -> [];
cipher([H|T]) ->
[H+10|cipher(T)]. %% Add 10 to each character code.
In the shell:
~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> my:cipher("ABC").
"KLM"
3>
By the way, all functions are "pattern matched", so saying "a pattern matched function" is redundant, you can just say, "a function".

Erlang printing hex instead of integer

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.

Value from binding in LFE interpreter using Erlang

I'd like to use Lisp Flavored Erlang as a scripting extension language for an Erlang application. If you want, in a similar way GNU Emacs is configured and extended via Emacs Lisp.
I know that the argument is wide and structured; but in the specific case of this question I'd like being able to read a binding name (or variable, if you prefer) defined in LFE from Erlang code.
I'm not an expert of LFE internal architecture (which is an excellent example of software engineering and Erlang programming), but I was not able to find an answer neither in the sources nor in the documentation.
Looking at sources I can see that LFE contains both a compiler that target Erlang VM and an interpreter.
The latter is the one I'm trying to use.
If I start Erlang shell/REPL in LFE installation path (on my system $HOME/opt/lfe):
$ cd /path/to/LFE-install-dir
$ erl -pa ./ebin
I'm able to calculate a value:
1> {ok, Expr} = lfe_io:read_string("(+ 1 10)").
{ok,['+',1,10]}
2> Result = lfe_eval:expr(Expr).
11
This is a first step, but not exactly what I want. I'd like rather to bind a variable and read its value; that's my issue:
3> {ok, Expr2} = lfe_io:read_string("(set a 10)").
{ok,[set,a,10]}
4> lfe_eval:expr(Expr2).
** exception error: {unbound_func,{set,2}}
in function lfe_eval:eval_expr/2
Why set is recognized as an unbound function? In LFE REPL this expression is valid:
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] ...
LFE Shell V6.4 (abort with ^G)
> (set a 10)
10
> a
10
I'm obviously using the API in the wrong way. How can I read the content of a and/or properly initialize the LFE interpreter?
(If this is explained somewhere, please provide the reference).
I won't attempt to answer completely your broader question about the "best practices" of adding scripting. It seems to me that choosing between "hook-based" solution (in which you define hook implementations by name convention and they are automatically recognized) and "explicit api" solution (in which you use functions predefinied in the scripting enviroment to register your hooks or otherwise call configuration functions) is largely a matter of taste. Explicit calls like (set-connection-timeout-handler ...) may be more readable, easier to debug (no misspelling problems, no surprises on api changes), easier to document, and a bit more flexible, but more, well, explicit.
Building from your simple variable definition example, here are a few ways you could get started going further the "interpreted" path:
1> {ok, Expr} = lfe_io:read_string("'((a 10))").
{ok,[quote,[[a,10]]]}
2> lfe_eval:expr (Expr).
[[a,10]]
3> EvalAll = fun (Conf) -> {ok, E} = lfe_io:read_string("'(" ++ Conf ++ ")"), lfe_eval:expr(E) end.
#Fun<erl_eval.6.90072148>
4> EvalAll ("(a 10) (b 11)").
[[a,10],[b,11]]
5> EvalAllL = fun (Conf) -> {ok, E} = lfe_io:read_string("(list " ++ Conf ++ ")"), lfe_eval:expr(E) end.
#Fun<erl_eval.6.90072148>
6> [{f, F}] = EvalAllL ("(tuple 'f (lambda (x) (+ 10 x)))").
[{f,#Fun<lfe_eval.12.2018457>}]
7> F (12).
22
8> G = fun (X) -> X * 2 end.
#Fun<erl_eval.6.90072148>
9> lfe_eval:expr (element (2, lfe_io:read_string ("(g 15)")), lfe_eval:add_lexical_func(g, 1, G, lfe_env:new ())).
30
A simple way is use to the 'lfe' command to run LFE scripts. The 'lfe' behaves in similar fashion to 'bash' in that you can use it to run scripts. The 'lfec' script defined in bin/lfec is a good example of this. It is an LFE shell script which parses it arguments and run the LFE compiler.

erlang method not called

Hi I have a sample erlang code as,
%%file_comment
-module(helloworld).
%% ====================================================================
%% API functions
%% ====================================================================
-export([add/2,subtract/2,hello/0,greet_and_math/1]).
%% ====================================================================
%% Internal functions
%% ====================================================================
add(A,B)->
A+B.
subtract(A,B)->
io:format("SUBTRACT!~n"),
A-B.
hello()->
io:format("Hello, world!~n").
greet_and_math(X) ->
hello(),
subtract(X,3),
add(X,2).
And when I run
helloworld:greet_and_math(15).
Output is:
Hello, world!
SUBTRACT!
17
My doubt is why A-B which is 15-2=13 not printed on console?
That's because you never printed 15-2. The code you need would look like this:
%%file_comment
-module(helloworld).
%% ====================================================================
%% API functions
%% ====================================================================
-export([add/2,subtract/2,hello/0,greet_and_math/1]).
%% ====================================================================
%% Internal functions
%% ====================================================================
add(A,B)->
A+B.
subtract(A,B)->
io:format("SUBTRACT!~n"),
io:format("~p~n", [A-B]). % this will make sure A-B is printed to console
hello()->
io:format("Hello, world!~n").
greet_and_math(X) ->
hello(),
subtract(X,3),
add(X,2).
That will give you:
Hello, world!
SUBTRACT!
12
17
If you wonder why 17 is printed, that's because it is the last expression. This one is always printed to console after executing code because it is actually what is returned by your code. Just execute io:format("hello~n"). on your console and you will see:
hello
ok
ok in this case is returned by io:format, and because it is the last expression, it will be printed.
io:format("hello~n"),
io:format("world~n").
will result in:
hello
world
ok
Only the last ok returned by the second io:format can be seen on console.
I hope you get the idea around how this works.
So in your case by typing:
4> A = helloworld:greet_and_math(15).
Hello, world!
SUBTRACT!
17
5> A.
17
6>
You see how 17 is the value returned by greet_and_math(15) because it is the last expression? And thus it can be assigned to a variable.
#a.w. it is not that the last value is automatically printed, it the shell which prints the value of the call you make. So when you call greet_and_math(15) the function will:
Call hello() which prints the greeting. Its return value of ok from the call to io:format is ignored.
Call subtract(X, 3). Its return value of 12 is ignored.
Call add(X, 2). Its return value of 17 then becomes the return value of the whole function.
It is this return value of 17 which the shell prints out. So:
Everything returns a value, you cannot not return a value.
Returning a value and printing a value are very different things.

Erlang atoms and ".."

This is output of erlang shell:
1> atom.
atom
2> next_atom.
next_atom
3> atom#erlang.
atom#erlang
4> 'atom in single quotes'.
'atom in single quotes'
5> atom = 'atom'.
atom
6> a.tom.
'a.tom'
7> a..tom.
* 1: syntax error before: '..'
When there is just one dot . within atom (line 6), I get no errors. However, when there is .., I get syntax error. Does .. have some special meaning in Erlang or why do I get error when . works fine?
Dots are not allowed as such in atoms, but a dot between two atoms: 'foo'.'bar',
is a compile time operator that concatenates the atoms to 'foo.bar'.
This is an extension which was made to support the (still not officially
supported) Java-like package system. That's why it's not documented.

Resources