How to call a printing function with more than two arguments on ERLANG? - erlang

So I've wrote this program that takes 1 String Argument and print it as following:
-module(sayhi).
-export([sayhi/1]).
sayhi({greeting, Greeting}) -> io:fwrite(Greeting).
then I call the function as following (from terminal).
c(sayhi).
ok
sayhi:sayhi({greeting, "HELLO!\n"}).
HELLO!
ok
Until now everything is good.
But When I try to implement 2 arguments, I get error:
*** argument 1: wrong number of arguments
Here is my Code:
-module(sayhi).
-export([sayhi/2]).
sayhi({greeting, Greeting}, {name, Name}) -> io:fwrite(Greeting, Name).
When I call my function:
sayhi:sayhi({greeting, "Hola "}, {name, "Sam"}).
The program Runs successfully but does not give me the output needed.
does the problem come from my statement of calling the function?
And what if I had 3, or even 10 arguments?

Erlang has a comprehensive documentation on all of its built-in functions, such as io:fwrite/1, io:fwrite/2, io:fwrite/3 (can be found here).
If you want to use the function with 1 argument, then you can call it like this:
io:fwrite(Greeting ++ Name). %% '++' is nothing but appending strings
io:fwrite(Greeting ++ Name ++ NextParam1 ++ NextParam2). %% You can then expand it as needed
When using 2 arguments, i.e. write(Format, Data), then:
io:fwrite("~s~s", [Greeting, Name]).
io:fwrite("~s~s~s~s", [Greeting, Name, NextParam1, NextParam2]). %% You can also expand as needed

You can also take advantage of what Erlang calls an iolist, which is a list containing certain types, which can be strings, and for an iolist Erlang will output the list as one string. For example:
-module(a).
-compile(export_all).
sayhi({greeting, Words})->
io:format(Words)
In the shell:
6> c(a).
a.erl:2:2: Warning: export_all flag enabled - all functions will be exported
% 2| -compile(export_all).
% | ^
{ok,a}
7> a:sayhi({greeting, ["Hello ", "Jim!"]}).
Hello Jim!ok
io:format() returns ok, and that's what you see at the end of the string. That's not the greatest solution because you have to add spaces to your words (notice the space in "Hello "). A better solution would be to automatically add spaces between words, then add a newline at the end so that the ok is on a separate line:
-module(a).
-compile(export_all).
sayhi({greeting, Words})->
WordsWithSpaces = add_spaces(Words, []),
io:format(WordsWithSpaces).
add_spaces([Word | []], Acc) ->
lists:reverse([$\n, Word | Acc]);
add_spaces([Word | Words], Acc) ->
add_spaces(Words, [" ", Word | Acc]).
In the shell:
18> c(a).
a.erl:2:2: Warning: export_all flag enabled - all functions will be exported
% 2| -compile(export_all).
% | ^
{ok,a}
19> a:sayhi({greeting, ["Hello", "Jim!", "Now", "goodbye!"]}).
Hello Jim! Now goodbye!
ok

Related

Implement a lists:map using case clauses instead of function clauses in Erlang

Can anyone tell me what this means? I am new to this and my friend recommended me to post in this website.
By the way I'm new to Erlang.
If possible I want to write a code in editor and I don't even understand the question any sample input/output and how it works an explanation will do. Thankyou
It seems to me that the question refers to the implementation of lists:map/2, a function that applies the same function (received as a parameter) to all elements of a list and returns the resulting list.
In other words, this function.
You can check the OTP Github repo to see how that function is implemented:
map(F, List) when is_function(F, 1) ->
case List of
[Hd | Tail] -> [F(Hd) | map_1(F, Tail)];
[] -> []
end.
map_1(F, [Hd | Tail]) ->
[F(Hd) | map_1(F, Tail)];
map_1(_F, []) ->
[].
Or you can conceive an even simpler implementation, as…
map(F, []) -> [];
map(F, [H|T]) -> [F(H) | map(F, T)].
Both of them (for the OTP version, I'm referring to map_1/2) use pattern-matching in function clause heads to distinguish between the base case and the recursive step of the function.
The request that you received is to implement the same algorithm using a single function clause with a case clause instead of the two function clauses you see above.
Here's a simple example showing how to use function clauses, then case statements to do the same thing. Put the following code in a file named a.erl in some directory:
-module(a).
-export([show_stuff/1, show_it/1]).
show_stuff(1) ->
io:format("The argument was 1~n");
show_stuff(2) ->
io:format("The argument was 2~n");
show_stuff(_)->
io:format("The argument was something other than 1 or 2~n").
show_it(X) ->
case X of
1 -> io:format("The argument was 1~n");
2 -> io:format("The argument was 2~n");
_ -> io:format("The argument was something other than 1 or 2~n")
end.
Note that the file name, a.erl and the module directive:
-module(a).
must match. So, if you named your file homework1.erl, then the module directive in the file must be:
-module(homework1).
To save a lot of typing, it's best to use very short module names (as you will see below).
In a terminal window, switch directories to the directory containing a.erl:
~$ cd erlang_programs/
then launch the erlang shell:
~/erlang_programs$ erl
Erlang/OTP 24 [erts-12.0.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]
Eshell V12.0.2 (abort with ^G)
Next, execute the following statements:
1> c(a). <--- Compiles the code in your file
{ok,a} <--- Or, you may get errors which must be corrected, then try recompiling.
2> a:show_stuff(1).
The argument was 1
ok
3> a:show_stuff(4).
The argument was something other than 1 or 2
ok
4> a:show_it(1).
The argument was 1
ok
5> a:show_it(4).
The argument was something other than 1 or 2
ok
6>
Note the syntax for calling a function defined in a file/module:
module_name:function_name(arg1, arg2, ... argn).
any sample input/output and how it works an explanation will do
In the documentaion linked in Brujo Benavides's answer, you can see:
Takes a function from As to Bs, and a list of As and produces a list of Bs by applying the function to every element in the list. This function is used to obtain the return values.
So F is a function (of a single argument) such as fun(X) -> X*2 end. See https://www.erlang.org/doc/programming_examples/funs.html#syntax-of-funs or https://www.erlang.org/doc/reference_manual/expressions.html#funs to understand fun expressions. List1 is a list of values which the function F can work on (in this case numbers) such as [1,2,3]. Then list:map(fun(X) -> X*2 end, [1,2,3]) calls fun(X) -> X*2 end on each element of list [1,2,3] and returns the list of return values [2,4,6]. Your function should give the same result on these arguments.

Implementation of split_binary function of Erlang

I'm new in the Erlang world. I'm trying to implement the function split_binary. The function takes as input (list, index) and it splits the list in two lists according to the index.
split(Lst, N) when N>=list:lenght(Lst) -> Lst;
split(Lst, N) when N<list:lenght(Lst) -> splitHelper(list:reverse(Lst), 0, N, []).
splitHelper([H|T], X, N, Acc) ->
if
X>=N ->
(list:reverse([H|T]), list:reverse(Acc));
X<N ->
splitHelper(T, X+1, N, [H|Acc])
end.
How can I improve my code?
I'm new in the Erlang world. I'm trying to implement the function
split_binary. The function takes as input (list, index) and it splits
the list in two lists according to the index.
According to the erlang docs for split_binary/2, the two arguments are a binary, which is not a list, and the number of bytes where you want to split the binary.
First, you need to have a basic understanding of what a binary is. A binary is a sequence of bytes, where each byte is 8 bits representing some integer, e.g.
0010 0001
which is 33. Here is an example of a binary:
<<1, 2, 3>>
When you don't specify a size for each integer, by default each integer will occupy one byte. If you wanted the 2 to occupy two bytes instead, i.e. 0000 0000 0000 0010, which is 16 bits, then you could write:
<<1, 2:16, 3>>
which the shell would display as:
<<1,0,2,3>>
Huh? Where did that 0 come from? The shell displays a binary byte by byte, and the first byte of the integer 0000 0000 0000 0010 is 0000 0000, which is 0.
Next, you can step through a binary just like you can for a list, extracting any number of bits at a time from the front of the binary. It so happens that split_binary/2 extracts 8 bits, or 1 byte, at a time from the head of the binary.
There are a couple of tricks to learning how to step through a binary:
For lists, [] means an empty list, and for binaries <<>> means an empty binary.
For lists you write [Head|Tail] to extract the head of the list, and for binaries you write <<Bits:3, Rest/binary>> to extract 3 bits from the front of the binary. In your case, you need to extract 8 bits from the front of the binary.
Here is an example of what you can do:
-module(a).
-compile(export_all).
split_b(Bin, N) ->
split_b(Bin, N, _Acc = <<>>).
split_b( Bin, _N = 0, Acc) -> [Acc, Bin];
split_b(<<Bits:8, Rest/binary>>, N, Acc) ->
split_b(Rest, N-1, <<Acc/binary, Bits>>).
In the shell:
40> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}
41> a:split_b(<<5,6,7>>, 1).
[<<5>>,<<6,7>>]
42> a:split_b(<<5,6,7>>, 2).
[<<5,6>>,<<7>>]
Note that when constructing a binary one of the segments of the binary can be another binary:
23> Bin = <<1, 2, 3>>.
<<1,2,3>>
24> Acc = <<Bin/binary, 4>>.
<<1,2,3,4>>
If you are actually trying to implement lists:split/2, you can do this:
-module(a).
-compile(export_all).
split_l(N, List) ->
split_l(N, List, _Acc=[]).
split_l(_N=0, List, Acc) ->
[lists:reverse(Acc), List];
split_l(N, [H|T], Acc) ->
split_l(N-1, T, [H|Acc]).
In the shell:
2> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}
3> a:split_l(1, [10, 20, 30]).
["\n",[20,30]]
4> shell:strings(false).
true
5> a:split_l(1, [10, 20, 30]).
[[10],[20,30]]
6> a:split_l(2, [10, 20, 30]).
[[10,20],[30]]
I think #7stud's answer is the best one, but I wanted to add a few minor details about your code, without actually checking if it works or not…
list:lenght/1 doesn't exist (unless you also created your own list module.
If you created your own list module, you can't use it in guards. Only BIFs are allowed there.
If you're trying to use stdlib's function to check the length of a list, then you should use erlang:length/1 or just length/1.
It's more idiomatic in Erlang to use snake_case (e.g. split_helper) instead of camelCase (e.g. splitHelper) for module names, function names and atoms in general.
You can use pattern-matching directly instead of writing an if as the sole expression of your function…
split_helper([H|T], X, N, Acc) when X > N ->
(list:reverse([H|T]), list:reverse(Acc));
split_helper([H|T], X, N, Acc) when X<N ->
split_helper(T, X+1, N, [H|Acc]).
Tuples are denoted with curly braces and not parentheses: {list:reverse([H|T]),…. BTW… This should have prevented your code from compiling at all. The error should've looked like syntax error before: ','
Also, you might have written your own list module, but if not and if you're trying to use stdlib functionality, it's lists:reverse/1 not list:reverse/1.
Finally, out of that list, I would strongly recommend you to write some simple tests for your code. This article may help you with that.

How to spawn process with arguments from erlang shell

I do not know what overload of spawn to use when launching a process from the erlang shell , since i need to pass arguments.
A=spawn(
fun(TID)->
receive {FROM,MSG}->
FROM ! {self(),MSG}
after 0 ->
TID !{self(),timeouted}
end
end,
TID
).
There is no overload for just the function and arguments.
What is the module name when launching from shell ?
I have also tried:
A=spawn(?MODULE,fun()->....,TID).
P.S
In my case as you can see i need to provide arguments to the spawn method , while running it directly from the erlang shell.
Just embed the definition in a fun:
A = fun(X) ->
TID = X,
spawn(
fun()->
receive {FROM,MSG}->
FROM ! {self(),MSG}
after 0 ->
TID !{self(),timeouted}
end
end
)
end.
and then you can use A(YourParam).
Typically, you define a function in a module:
-module(a).
-compile(export_all).
go(X)->
receive {From, Msg}->
From ! {self(), Msg}
after 0 ->
io:format("~s~n", [X])
end.
Then do this:
9> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}
10> Pid = spawn(a, go, ["hello"]).
hello
<0.95.0>
Defining functions in the shell is too much of a pain in the ass.
Response to comment:
Here's how you can do simple testing in erlang:
-module(a).
-compile(export_all).
-include_lib("eunit/include/eunit.hrl").
do(Y) ->
Y.
go(X)->
receive {From, Msg}->
From ! {self(), Msg}
after 0 ->
X
end.
do_test() ->
10 = do(10).
go_test() ->
"hello" = go("hello").
In the shell:
1> c(a).
2> a:test().
2 tests passed.
ok
Here's what happens when a test fails:
5> a:test().
a: go_test...*failed*
in function a:go_test/0 (a.erl, line 18)
**error:{badmatch,"hello"}
output:<<"">>
=======================================================
Failed: 1. Skipped: 0. Passed: 1.
error
6>
You don't even need to use eunit because you can simply do:
go_test() ->
"hello" = go("hello").
Then in the shell:
1> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
2> a:go_test().
You'll get a bad match error if go("hello") doesn't return "hello":
** exception error: no match of right hand side value "hello"
in function a:go_test/0 (a.erl, line 18)
The advantage of using eunit is that with one command, a:test(), you can execute all the functions in the module that end in _test.

Erlang, Matching with list foreach

I've been making a chat application in Erlang for a school project, but I've run into an issue. I'm trying to make my program concurrent and in order to do so I start a new thread for each message a channel is sending. I do this using lists:foreach, but I want to make sure that I don't message the person who typed in the channel.
request(State, {message, {UserID,UserPID}, Token}) ->
case catch lists:member({UserID,UserPID}, State#channel.users) of
false ->
{{error, user_not_joined}, State};
true ->
spawn( fun() ->
ListOfUsers = State#channel.users,
UserPIDs = lists:map(fun ({_, V}) -> V end, ListOfUsers),
%spawn( fun() ->end)
lists:foreach(
fun(UserPID) -> ok end,
fun(PID) ->
spawn( fun() -> genserver:request(PID, {message_from_server, State#channel.name, UserID, Token}) end)
end, UserPIDs) end),
{ok, State}
end;
What I pretty much want to do is to match with the UserPID inside the foreach. As of now I only get warnings:
channel.erl:39: Warning: variable 'UserPID' is unused
channel.erl:39: Warning: variable 'UserPID' shadowed in 'fun'
Line 3 is fun(UserPID) -> ok end,
Cheers
The answer by legoscia is fine, but I'd add that often list comprehension is simpler to use and simpler to read than lists:foreach. Note that list comprehension is able to ignore values based on clauses. Consider the following example:
-module(filter).
-export([do/0]).
do() ->
Values = lists:seq(1,10),
IgnoreThisValue = 5,
%% print all values unequal to IgnoreThisValue
[io:format("Value: ~b~n", [Value]) ||
Value <- Values, Value =/= IgnoreThisValue],
ok.
Run it in the shell:
1> make:all([load]).
Recompile: filter
up_to_date
2> filter:do().
Value: 1
Value: 2
Value: 3
Value: 4
Value: 6
Value: 7
Value: 8
Value: 9
Value: 10
A side note on your code: Why do you spawn a thread per process? I assume that you are using the behaviour gen_server (correct me if I am wrong). If so, you should consider using the cast function to simply send a message. As you do not check the result of genserver:request/2, this might be a viable option which saves you a lot of processes.
Since the function argument shadows the existing variable, you need to use a guard for that:
fun(PID) when PID =:= UserPID -> ok end

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