Erlang - case construction - erlang

I'm new to Erlang and I've tried some Erlang constructions.
My program should behave something like that:
if x == 42:
print "Hi"
else:
print "Hello"
Here is my code in Erlang
-module(tested).
-export([main/0]).
main() ->
{ok, X} = io:fread("","~d"),
case X == 42 of
true -> io:fwrite("Hi\n");
false -> io:fwrite("Hello\n")
end.
Thanks in advance for help.

Use {ok, [X]} = io:fread("","~d") (brackets around X).
fread returns a list as the second element of the tuple (which makes sense in case you're reading more than one token), so you need to get the element out of the list before you can compare it to 42.
Note that instead of pattern matching on the result of ==, you could simply pattern match on X itself, i.e.:
case X of
42 -> io:fwrite("Hi\n");
_ -> io:fwrite("Hello\n")
end.

Related

Understanding Erlang List Comprehension Generators

Given this function:
pretty_print(Folders, Depth) ->
{CurrrentFolder, ListSubfolders} = Folders,
SignTemp = lists:duplicate(Depth, "-"),
case Depth of
0 -> Sign = SignTemp;
_ -> Sign = "|" ++ SignTemp
end,
io:format("~s~s~n", [Sign, CurrrentFolder]),
[pretty_print(Subfolder, Depth+1)|| Subfolder <- ListSubfolders].
What happens to a recursive function in Erlang when in a list comprehension the generator is null or empty?
So when the variable is empty, the function won't call itself?
Won't it produce an error on that line? There is nothing to control that an error does not occur in this line?
{CurrrentFolder, ListSubfolders} = Folders,
For example in this piece of code, the behaviour of another variable through Depth is controlled:
case Depth of
0 -> Sign = SignTemp;
_ -> Sign = "|" ++ SignTemp
end,
There is something that I do not quite understand here.
What happens to the function when it reaches the last folder of a directory?
¿What happens to a recursive function in Elrang when in a list comprehesion the generator is null or empty?
When a generator in a list comprehension is empty, then the comprehension is empty. Doesn't matter if it's recursive or not.
So when the variable is empty, the function won't call itself?
Yes.
There is nothing to control that an error does not occur in this line?
No, it simply assumes the caller will give an argument which matches it (and that ListSubfolders is a list each element of which also matches it). It would be more idiomatic to match directly in the head:
pretty_print({CurrrentFolder, ListSubfolders}, Depth) ->
SignTemp = lists:duplicate(Depth, "-"),
... %% the rest is the same
What happens to a recursive function in Elrang when in a list
comprehesion the generator is null or empty?
Easy to test:
-module(a).
-compile(export_all).
go(N) ->
[go(X) || X <- [] ].
In the shell:
3> a:go(0).
[]
What would you expect the return value of the following to be:
[ X+1 || X <- [] ]
No different than if you defined:
f(X) -> X+1.
then executed:
[f(X) || X <- [] ]
The function doesn't get called if there is no argument to call the function with.
Just to add more clarity. Below code is not there for the purpose of control - they are 'just' there because for root folder input, we do not want to put '|' character in the front of the folder name (cosmetic stuff). So even if you change it to whichever: Sign = SignTemp or Sign = "|" ++ SignTemp only, it won't change the logic.
case Depth of
0 -> Sign = SignTemp;
_ -> Sign = "|" ++ SignTemp
end,
In the previous code, Folders will never be [], it will at least have the value of {CurrentFolder, []} (the one that could be an empty list is ListSubfolders).
And since below list comprehension is applied to ListSubfolders, it is safe because if ListSubfolders is [], pretty_print will not be called.
[pretty_print(Subfolder, Depth+1)|| Subfolder <- ListSubfolders].
I draw this to illustrate how the list comprehension works, with all recursive call of your function pretty_print.

Returning value from if else in ERLANG

parse(Tuples,Str,Block) ->
if Block =:= 1 ->
Str1=string:substr(Str,1,1),
Str2=string:substr(Str,2,4),
Tuple2=Tuples++[{a,Str1},{b,Str2}];
Block =:= 2 ->
Str3=string:substr(Str,1,1),
Str4=string:substr(Str,2,3),
Tuple2=Tuples++[{c,Str3},{d,Str4};
true-> ok
end.
I am a newbie to erlang. Is there a way to return the tuple2 value from this function? if not what is the work around?
when i try to return Tuple2 after end it gives
variable 'Tuple2' unsafe in 'if'.
and when i use it above 'if' the Tuple2 cannot be altered.
In your code, Tuple is being 'returned' in the first two cases. Remember, in Erlang the last expression is always used as the return value. The reason you get the warning is that Tuple2 is not given a value in all branches. For example, what if Block was 3? Tuple2 would not be defined.
Let's rewrite this in a more idiomatic way to better see what is returned:
parse(Tuples,Str,Block) ->
case Block of
1 ->
Str1=string:substr(Str,1,1),
Str2=string:substr(Str,2,4),
Tuple2=Tuples++[{a,Str1},{b,Str2}];
2 ->
Str3=string:substr(Str,1,1),
Str4=string:substr(Str,2,3),
Tuple2=Tuples++[{c,Str3},{d,Str4};
_ ->
ok
end.
The last expression in each branch of the case expression will be 'returned'.
If you don't see this, consider the following:
1> case 1 of
1> 1 -> ok;
1> 2 -> nok
1> end.
ok
ok is 'returned' from that case expresion (the case expression evaluates to ok).
Let's rewrite the original code to be even more idiomatic:
parse(Tuples, Str, 1) ->
Str1=string:substr(Str,1,1),
Str2=string:substr(Str,2,4),
Tuple2=Tuples++[{a,Str1},{b,Str2}];
parse(Tuples, Str, 2) ->
Str3=string:substr(Str,1,1),
Str4=string:substr(Str,2,3),
Tuple2=Tuples++[{c,Str3},{d,Str4};
parse(_, _, _) ->
ok.

How do I choose the first tuple within a list and save the rest of the tuples in Erlang?

I want be able to input the following:
fun([{X,Y}, {A,B}, {M,N}]).
and only use the first tuple and save the others for later use. I tried defining it like this:
fun([{X|Y}, V]) ->
V.
But I just get a syntax error before the "|". "V" was just to try and output to see what was happening.
Is there any resources I can be pointed towards for some support with this? Or am I doing something really wrong?
func([{X,Y}| V]) -> %% fun is a keyword, you cannot use it as a function name
%% do some stuff with X, Y
V.
generally, if you want to apply the same function to all element of a list, it is good to use the lists module: (lists:foreach/2, lists:map/2, lists:foldl/2 ...) or a list comprehension
Res = [Fun(T) || T <- L]
wher Fun is the function to apply to each tuple T from the list L
you should write like this:
fun([{X, Y} | V]).
[{X, Y} | V] = [{X,Y}, {A,B}, {M,N}], then V = [{A,B}, {M,N}]

Pattern matching on bson tuples

The bson-erlang module turns BSON-encoded JSON such as this:
{ "salutation" : "hello",
"subject" : "world" }
Into an Erlang tuple like this:
{ salutation, <<"hello">>, subject, <<"world">> }
Now, the server I'm attempting to talk to can put those fields in any order, and there might be extra fields in there that I don't care about, so -- equally validly -- I might see this instead:
{ subject, <<"world">>, salutation, <<"hello">>, reason, <<"nice day">> }
Is there any way that I can specify a function pattern that extracts a particular piece of the tuple, based on the one appearing immediately before it?
If I try the following, it fails with "no function clause matching..." because the arity of the tuple is wrong, and because the fields that I care about aren't in the correct place:
handle({ salutation, Salutation, _, _ }) -> ok.
Is this possible? Is there a better way to do this?
T = { subject, <<"world">>, salutation, <<"hello">>, reason, <<"nice day">> },
L = size(T),
L1 = [{element(I,T),element(I+1,T)} || I <- lists:seq(1,L,2)].
[{subject,<<"world">>},
{salutation,<<"hello">>},
{reason,<<"nice day">>}]
proplists:get_value(salutation,L1).
<<"hello">>
and if you want all in 1:
F = fun(Key,Tup) -> proplists:get_value(Key,[{element(I,Tup),element(I+1,Tup)} || I <- lists:seq(1,size(Tup),2)]) end.
F(reason,T).
<<"nice day">>
F(foo,T).
undefined
There is no pattern that successfully matches values from a variable-length structure after a prefix of an unknown length. This is true for tuples, lists and binaries. Indeed, such a pattern would require to recurse through the structure.
A common approach for a list is to recurse by splitting head and tail, something typical of functional languages.
f_list([salutation, Salutation | _]) -> {value, Salutation};
f_list([_Key, _Value | Tail]) -> f_list(Tail);
f_list([]) -> false.
Please note that this function may fail if the list contains an odd number of elements.
The same approach is possible with tuples, but you need guards instead of matching patterns as there is no pattern to extract the equivalent of the tail of the tuple. Indeed, tuples are not linked lists but structures with a O(1) access to their elements (and their size).
f_tuple(Tuple) -> f_tuple0(Tuple, 1).
f_tuple0(Tuple, N) when element(N, Tuple) =:= salutation ->
{value, element(N + 1, Tuple)};
f_tuple0(Tuple, N) when tuple_size(Tuple) > N -> f_tuple0(Tuple, N + 2);
f_tuple0(_Tuple, _N) -> false.
Likewise, this function may fail if the tuple contains an odd number of elements.
Based on elements in the question, the advantage of guards over bson:at/2 is unclear, though.

Convert a string into a fun

I'm trying to get around a problem with file:consult/1 not allowing tuples with fun in them like in this example:
{add_one, fun(X) -> X+1 end}.
To get around this I'm considering writing the fun inside a string and evaluating it
{add_one, "fun(X) -> X+1 end"}.
The question is. How do I convert the string into a fun?
parse_fun_expr(S) ->
{ok, Ts, _} = erl_scan:string(S),
{ok, Exprs} = erl_parse:parse_exprs(Ts),
{value, Fun, _} = erl_eval:exprs(Exprs, []),
Fun.
Note that you need a period at the end of your fun expression, e.g. S = "fun(X) -> X + 1 end.".
file:script/1 almost does what you want - it evaluates a series of erlang expressions from a file and returns the last result. You could use it in place of file:consult/1 but you'd need to change the format of the file from "term. term. term." giving [term, term ,term] to "[term, term , term]." giving [term, term, term] - place a single expression in the file instead of a sequence.
I'd like to point out that Zed's answer creates an interpreted fun. When the fun is called it enters the evaluator which starts to evaluates the abstract syntax tree returned by erl_parse:parse_exprs/1 that it has captured. Looking at the fun created:
11> erlang:fun_info(Fun, env).
{env,[[],none,none,
[{clause,1,
[{var,1,'X'}],
[],
[{op,1,'+',{var,1,'X'},{integer,1,1}}]}]]}
12> erlang:fun_info(Fun, module).
{module,erl_eval}
One can see that it has closed over the parsed abstract syntax tree as seen in the env info, and it is a fun created inside erlang_eval as seen in the module info.
It is possible to use the erlang compiler to create a compiled module at runtime, and a pointer toward that is compile:forms/2 and code:load_binary/3. But the details of that should probably go into another stackoverflow question.
Maybe by using the erl_eval module?
2> F =fun(Str,Binding) ->
{ok,Ts,_} = erl_scan:string(Str),
Ts1 = case lists:reverse(Ts) of
[{dot,_}|_] -> Ts;
TsR -> lists:reverse([{dot,1} | TsR])
end,
{ok,Expr} = erl_parse:parse_exprs(Ts1),
erl_eval:exprs(Expr, Binding) end.
#Fun<erl_eval.12.111823515>
3> F("A=23.",[]).
{value,23,[{'A',23}]}
5> F("12+B.",[{'B',23}]).
{value,35,[{'B',23}]}

Resources