Knowing the number of parameters of a passed function (erlang) - erlang

In ERLANG: Assume we have a function f() that takes F1 as inputs where F1 is a function. Is there a way to know the number of input parameters of F1.
I feel somehow there IS a solution, but I am not sure. for instance:
-module(high).
-compile(export_all).
f1() -> 1.
f2(X) -> X.
f3(X, Y) -> {X,Y}.
run(F) -> io:format("F ~p ~n", [F]).
So, is there any way for function run/1 to know information about the passed function [mainly the number of input parameters of the passed function].
Note: Please be informed that this is a theoretical question.
Note: is the code of apply(fun,[arguments]) available in open-source .. this may hep me I guess.

erlang:fun_info(Fun,arity).
For example
F = fun(A,B) -> A+B end.
#Fun<erl_eval.12.111823515>
3> erlang:fun_info(F,arity).
{arity,2}

You can use module_info/1 to get info about your module.
module_info/1
The call module_info(Key), where Key is an atom, returns a single piece of information about the module.
The following values are allowed for Key:
...
exports
Returns a list of {Name,Arity} tuples with all exported functions in the module.
functions
Returns a list of {Name,Arity} tuples with all functions in the module.
http://erlang.org/doc/reference_manual/modules.html
run(F) -> find_value(F,module_info(exports)).
find_value(Key, List) ->
case lists:keyfind(Key, 1, List) of
{Key, Result} -> {Key,Result};
false -> io:format("There is no function called ~w.~n", [Key])
end.

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.

Understanding '_' variable in Erlang

Erlang newbie here. I am from a Java background and am finding Erlan rather interesting. Am following the excellent book "Learn You some Erlang".
Here's an example for recursion as given in the book for reversing the order of a List:
tail_reverse(L) -> tail_reverse(L,[]).
tail_reverse([],Acc) -> Acc;
tail_reverse([H|T],Acc) -> tail_reverse(T, [H|Acc]).
This works as expected. However, if I changed the code to:
tail_reverse(L) -> tail_reverse(L,[]).
tail_reverse([],_) -> [];
tail_reverse([H|T],Acc) -> tail_reverse(T, [H|Acc]).
this now always returns [] irrespective of the contents of the List passed. So it seems that the line tail_reverse([],_) -> []; is the one getting called. However, my understanding is that it should be called only if the first parameter is empty and _ is just a placeholder.
What am I missing here?
This line:
tail_reverse([], Acc) -> Acc
is supposed to return the accumulating argument Acc when the processed list becomes empty. You replaced it with:
tail_reverse([], _) -> []
which is executed in the same case (the bottom of the recursion), but ignores the previously done work and returns the empty list.
As for the _ variable, it has not much to do with your problem, but it's explained in this answer.
#bereal's answer is correct. However, I am going to provide my own answer to general question of "How does the _ variable work in Erlang. I recently wrote a blog post on the _ variable:
The anonymous variable is denoted by a single underscore (_). The anonymous variable is used when a variable is required but the value needs to be ignored. The anonymous variable never actually has the value bound to it. Since the value is never bound it can be used multiple times in a pattern and each time it is allowed to match a different value. Example:
1> {_, _} = {foo, bar}.
{foo, bar}
2> _.
* 1: variable '_' is unbound
4> {_, Second} = {foo, bar}.
{foo, bar}
5> _.
* 1: variable '_' is unbound
6> Second.
bar
More is available here:
http://stratus3d.com/blog/2014/11/05/everything-you-need-to-know-about-erlangs-magic-variable/

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

Why does Erlang allow putting parentheses after a fun?

This question is about some syntax a partner came across today and though we understand how it works, we don't understand why is it allowed (what is its use?).
Look at this snippet:
fun() -> ok end().
Without the last pair of parentheses this will produce something like:
#Fun<erl_eval.20.82930912>
But with them, the function is evaluated producing:
ok
My question is, why is that syntax allowed in Erlang ? why would I want to create a function just to call it immediately instead of just writing out its contents? is there any practical use to it ?
The only thing we could think about was introducing local variables inside the fun's body (but that would look ugly and unclear to me).
Please note that this other syntax is not allowed in Erlang, even though it follows the same concept of the former:
fun() -> fun() -> ok end end()().
(It would mean: a function A that returns a function B. And I'm evaluating A (thus producing B) and then evaluating B to get 'ok').
The syntax you mentioned is a natural outcome of Erlang's being functional.
In Erlang, functions are values (stored as closures).
The value of fun() -> ok end is a function, which takes nothing and returns ok. When we put parentheses after it, we are calling that function. Another way to demonstrate this is:
> F = fun() -> ok end.
#Fun<erl_eval.20.80484245>
> F().
ok
The functions in the second example of yours need to be grouped properly in order for the parser to make sense of them.
As for your question -- "why this syntax is allowed", I'd have to say it's a natural outcome of functions being values in Erlang. This ability enables the functional style of programming. Here is an example:
> lists:map(fun(X) -> X * 2 end, [1,2,3]).
[2,4,6]
The above code is in essence this:
> [fun(X) -> X * 2 end(1), fun(X) -> X * 2 end(2), fun(X) -> X * 2 end(3)].
[2,4,6]
A "natural outcome" is just a natural outcome, it really doesn't have to be of any practical use. So, you will probably never see code like (fun() -> fun() -> ok end end())(). being used:)
You typically wont't have much use for the syntax fun() -> ok end (). But it can be useful to do something like (find_right_fun()) (), which is basically the same thing - an expression that evaluates to a function.
Note that the Erlang parser requires you to specify the precedence using () to sort out the meaning of ()(), i.e. your second example should be (fun() -> fun() -> ok end 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