String template with erlang - erlang

With language like JS it's really easy to write something like:
var a = 5;
console.log(a + ' times\n');
how can I write the same code with erlang?

If your question is about stringification of any Erlang term, there is ~p in io:format/2,3 function.
A = 5, io:format("~p times~n", [A]).
If you are interested in debugging output, there is also erlang:display/1 function. It works like io:format("~p~n", [X]), true..

Related

What is the Erlang way to do stream manipulations?

Suppose I wanted to do something like:
dict
.values()
.map(fun scrub/1)
.flatMap(fun split/1)
.groupBy(fun keyFun/1, fun count/1)
.to_dict()
What is the most elegant way to achieve this in Erlang?
There is no direct easy way of doing that. All attempts I saw looked even worse than straightforward composition. If you will look at majority of open source project in Erlang, you will find that they use generic composition. Re-using your example:
to_dict(
groupBy(fun keyFun/1, fun count/1,
flatMap(fun split/1,
map(fun scrub/1,
values(dict))))).
This isn't a construct that's natural in Erlang. If you have a couple functions, regular composition is what I'd use:
lists:flatten(lists:map(fun (A) ->
do_stuff(A)
end,
generate_list())).
For a longer series of operations, intermediary variables:
Dict = #{hello => world, ...},
Values = maps:values(Dict),
ScrubbedValues = lists:map(fun scrub/1, Values),
SplitValues = lists:flatten(lists:map(fun split/1, ScrubbedValues)),
GroupedValues = basil_lists:group_by(fun keyFun/1, fun count/1, SplitValues),
Dict2 = maps:from_list(GroupedValues).
That's how it'd look if you wanted all of those operations grouped in one shot together.
However, I'd more likely write this in a different way:
-spec remap_values(map()) -> map().
remap_values(Map) ->
map_values(maps:values(Map)).
-spec map_values(list()) -> map().
map_values(Values) ->
map_values(Values, [], []).
-spec map_values(list(), list(), list()) -> map().
map_values([], OutList, OutGroup) ->
%% Base case: transform into a map
Grouped = lists:zip(OutGroup, OutList),
lists:foldl(fun ({Group, Element}, Acc = #{Group := Existing}) ->
Acc#{Group => [Element | Existing]};
({Group, Element}, Acc) ->
Acc#{Group => [Element]}
end,
#{},
Grouped;
map_values([First|Rest], OutList, OutGroup) ->
%% Recursive case: categorize process the first element and categorize the result
Processed = split(scrub(First)),
Categories = lists:map(fun categorize/1, Processed),
map_values(Rest, OutList ++ Processed, OutGroup ++ Categories).
The actual correct implementation depends a lot on how the code's going to be run -- what I've written here is pretty simple, but might not perform well on large amounts of data. If you're actually looking to process an endless stream of data you'll need to write that yourself (though you may find Gen Servers to be a very useful framework for doing so).

Transfer data in .txt file in erlang

I work in erlang
Now, I have a big problem
I want to have a log from a table mnesia and this log should be write in excel file
So the goal is write data from table mnesia to the excel file
I think and this is related to some code find in this forum that the best way is to write .txt file then transfer data from .txt file to excel file
I find this code in this forum in this link.
exporttxt()->
F = fun(T) -> mnesia:foldl(fun(X,Acc) -> [X|Acc] end, [],T) end,
{atomic,L} = mnesia:transaction(F(user)),
file:write_file("test.txt",[io_lib:format("~p\t~p\t~p~n",[F1,F2,F3]) ||
#user{id = F1,adress = F2,birthday = F3} <- L]).
But this code produces an error
As commented, the problem is clearly explained in the link itself. If you want the code then here it is. But please understand before directly jumping into the code.
exporttxt()->
F = fun() -> mnesia:foldl(fun(X,Acc) -> [X|Acc] end, [],user) end,
{atomic,L} = mnesia:transaction(F),
file:write_file("test.txt",[io_lib:format("~p\t~p\t~p~n",[F1,F2,F3]) ||
#user{id = F1,adress = F2,birthday = F3} <- L]).
in the subject you mention, I said that I didn't test the code, and of course there was a syntax error.
Here is a code that run.
1> ok = mnesia:create_schema([node()]).
ok
2> rd(my_user,{firstname,lastname,age}).
my_user
3> ok =application:start(mnesia).
ok
4> {atomic,ok} = mnesia:create_table(my_user,[{attributes,record_info(fields,my_user)},{disc_copies,[node()]},{type,bag}]).
{atomic,ok}
5> Add_user = fun(Fn,Ln,Ag) ->
5> F = fun() -> mnesia:write(my_user,#my_user{firstname=Fn,lastname=Ln,age=Ag},write) end,
5> mnesia:activity(transaction,F)
5> end.
#Fun<erl_eval.18.82930912>
6> ok = Add_user("Georges","Boy",25).
ok
7> ok = Add_user("Joe","Armstrong",52).
ok
8> ok = Add_user("Pascal","Me",55).
ok
9> F = fun(T) -> mnesia:foldl(fun(X,Acc) -> [X|Acc] end, [],T) end.
#Fun<erl_eval.6.82930912>
10> {atomic,L} = mnesia:transaction(F,[my_user]).
{atomic,[#my_user{firstname = "Pascal",lastname = "Me",
age = 55},
#my_user{firstname = "Joe",lastname = "Armstrong",age = 52},
#my_user{firstname = "Georges",lastname = "Boy",age = 25}]}
11> ok = file:write_file("test.txt",[io_lib:format("~p\t~p\t~p~n",[F1,F2,F3]) || #my_user{firstname = F1, lastname = F2, age = F3} <- L]).
ok
12>
you will have in your working directory a file named test.txt containing
"Pascal" "Me" 55
"Joe" "Armstrong" 52
"Georges" "Boy" 25
and if you open it with excel you will get
But this is not a code sequence you should use directly.
line 1 should take place in a code use for the deployment of your application.
line 2 is a record definition, necessary for the shell to understand the next lines. It should be replaced by a -record(...) in a module or an included file.
lines 3 and 4 should take place in the init function of one of the higher level supervisor (with some test to check already started application, existing table...)
line 5 should be in the interface definition of a server
line 6,7,8 should be generated by a user interface in some client
and last line 9,10,11 in another interface (for admin?).
Message to Lost_with_coding and his fellows,
If I may give you my opinion, you are burning steps. You should focus on mastering the Erlang syntax, the concept of pattern matching and variable bounding... after you should look at more advance construction such as list and binary comprehensions. Take time to look at error messages and use them to solve simple problems. The official Erlang documentation is great for this purpose. I always have it open in my browser and sometimes I also use this link http://erldocs.com/R15B/ when I look for function I don't know.
Next will come higher order functions, error handling, processes, concurrency, OTP... plus the usage of the efficient but not sexy Erlang tools (tv, appmon, debugger...).
I recommend it very often, but use the fantastic Fred Hebert's web site http://learnyousomeerlang.com/ and follow it step by step, rewriting the code, not copy/paste; it really worths the effort.

Syntactic tree of a simple instruction : A = 2+3

i was wondering if anyone could help me drawing the syntactic tree of a very very simple instruction in erlang : a simple assignment like A = 2 + 3. using , of course the erlang official grammar available at http://svn.ulf.wiger.net/indent/trunk/erl_parse.yrl
Thanks for everything
You can simply use Erlang own tools:
1> {ok, Toks, _} = erl_scan:string("A=2+3.").
{ok,[{var,1,'A'},
{'=',1},
{integer,1,2},
{'+',1},
{integer,1,3},
{dot,1}],
1}
2> {ok, [AST]} = erl_parse:parse_exprs(Toks).
{ok,[{match,1,
{var,1,'A'},
{op,1,'+',{integer,1,2},{integer,1,3}}}]}
3> AST.
{match,1,{var,1,'A'},{op,1,'+',{integer,1,2},{integer,1,3}}}

Creating an AST node in Erlang

I am playing about with Erlang and I am trying to write a simple arithmetic parser.
I want to try and parse the following expression:
((12+3)-4)
I want to parse the expression into a stack of AST nodes. When parsing this expression, I would first of all create a binary expression for the (12+3) expression which would look something like this in C#:
var binaryStructure = new BinaryStructure();
binaryStructure.Left = IntegerLiteralExpression(12);
binaryStructure.Right = IntegerLiteralExpression(4);
binaryStructure.Operator = binaryExpression.Operator != BinaryOperatorType.Addition;
I am quite new to Erlang and I am wondering how I would go about creating a structure like this in Erlang that I can place on a List that I would use as the stack of expressions.
Can anyone suggest how to create such a tree like structure? Would a function be a good fit?
In functional language like Erlang it is far simpler. Just make it
{'+', 12, 3}
In more abstract way
A = 12,
B = 3,
OP = '+',
{OP, A, B}.
Also, have a look to the erl_parse.erl module in the stdlib application.
Reading from to the mkop function:
mkop(L, {Op,Pos}, R) -> {op,Pos,Op,L,R}.
mkop({Op,Pos}, A) -> {op,Pos,Op,A}.

How to turn a string with a valid Erlang expression into an abstract syntax tree (AST)?

I would like to convert a string containing a valid Erlang expression to its abstract syntax tree representation, without any success so far.
Below is an example of what I would like to do. After compiling, alling z:z(). generates module zed, which by calling zed:zed(). returns the result of applying lists:reverse on the given list.
-module(z).
-export([z/0]).
z() ->
ModuleAST = erl_syntax:attribute(erl_syntax:atom(module),
[erl_syntax:atom("zed")]),
ExportAST = erl_syntax:attribute(erl_syntax:atom(export),
[erl_syntax:list(
[erl_syntax:arity_qualifier(
erl_syntax:atom("zed"),
erl_syntax:integer(0))])]),
%ListAST = ?(String), % This is where I would put my AST
ListAST = erl_syntax:list([erl_syntax:integer(1), erl_syntax:integer(2)]),
FunctionAST = erl_syntax:function(erl_syntax:atom("zed"),
[erl_syntax:clause(
[], none,
[erl_syntax:application(
erl_syntax:atom(lists),
erl_syntax:atom(reverse),
[ListAST]
)])]),
Forms = [erl_syntax:revert(AST) || AST <- [ModuleAST, ExportAST, FunctionAST]],
case compile:forms(Forms) of
{ok,ModuleName,Binary} -> code:load_binary(ModuleName, "z", Binary);
{ok,ModuleName,Binary,_Warnings} -> code:load_binary(ModuleName, "z", Binary)
end.
String could be "[1,2,3].", or "begin A=4, B=2+3, [A,B] end.", or anything alike.
(Note that this is just an example of what I would like to do, so evaluating String is not an option for me.)
EDIT:
Specifying ListAST as below generates a huge dict-digraph-error-monster, and says "internal error in lint_module".
String = "[1,2,3].",
{ok, Ts, _} = erl_scan:string(String),
{ok, ListAST} = erl_parse:parse_exprs(Ts),
EDIT2:
This solution works for simple terms:
{ok, Ts, _} = erl_scan:string(String),
{ok, Term} = erl_parse:parse_term(Ts),
ListAST = erl_syntax:abstract(Term),
In your EDIT example:
String = "[1,2,3].",
{ok, Ts, _} = erl_scan:string(String),
{ok, ListAST} = erl_parse:parse_exprs(Ts),
the ListAST is actually a list of AST:s (because parse_exprs, as the name indicates, parses multiple expressions (each terminated by a period). Since your string contained a single expression, you got a list of one element. All you need to do is match that out:
{ok, [ListAST]} = erl_parse:parse_exprs(Ts),
so it has nothing to do with erl_syntax (which accepts all erl_parse trees); it's just that you had an extra list wrapper around the ListAST, which caused the compiler to puke.
Some comments of the top of my head.
I have not really used the erl_syntax libraries but I do think they make it difficult to read and "see" what you are trying to build. I would probably import the functions or define my own API to make it shorter and more legible. But then I generally tend to prefer shorter function and variable names.
The AST created by erl_syntax and the "standard" one created by erl_parse and used in the compiler are different and cannot be mixed. So you have to choose one of them and stick with it.
The example in your second EDIT will work for terms but not in the more general case:
{ok, Ts, _} = erl_scan:string(String),
{ok, Term} = erl_parse:parse_term(Ts),
ListAST = erl_syntax:abstract(Term),
This because erl_parse:parse_term/1 returns the actual term represented by the tokens while the other erl_parse functions parse_form and parse_exprs return the ASTs. Putting them into erl_syntax:abstract will do funny things.
Depending on what you are trying to do it might actually be easier to actually write out and erlang file and compile it rather than working directly with the abstract forms. This goes against my ingrained feelings but generating the erlang ASTs is not trivial. What type of code do you intend to produce?
<shameless_plug>
If you are not scared of lists you might try using LFE (lisp flavoured erlang) to generate code as with all lisps there is no special abstract form, it's all homoiconic and much easier to work with.
</shameless_plug>
Zoltan
This is how we get the AST:
11> String = "fun() -> io:format(\"blah~n\") end.".
"fun() -> io:format(\"blah~n\") end."
12> {ok, Tokens, _} = erl_scan:string(String).
{ok,[{'fun',1},
{'(',1},
{')',1},
{'->',1},
{atom,1,io},
{':',1},
{atom,1,format},
{'(',1},
{string,1,"blah~n"},
{')',1},
{'end',1},
{dot,1}],
1}
13> {ok, AbsForm} = erl_parse:parse_exprs(Tokens).
{ok,[{'fun',1,
{clauses,[{clause,1,[],[],
[{call,1,
{remote,1,{atom,1,io},{atom,1,format}},
[{string,1,"blah~n"}]}]}]}}]}
14>

Resources