[erlang-questions] How do funs work ?
Yoshihiro Tanaka
hirotnkg@REDACTED
Thu Mar 29 18:55:20 CEST 2012
2012/3/29 黃耀賢 (Yau-Hsien Huang) <g9414002.pccu.edu.tw@REDACTED>:
> On Wed, Mar 28, 2012 at 4:51 PM, Yoshihiro Tanaka <hirotnkg@REDACTED>
> wrote:
>>
>> Hello,
>>
>> I have a function which returns fun as below:
>>
>> make_fun(_, [], F) -> F;
>> make_fun(Operator, [Operand1, Operand2|Operands], F) ->
>> F2 = case Operator of
>> plus -> fun() -> Operand1 + Operand2 + F() end;
>> minus -> fun() -> Operand1 - Operand2 + F() end
>> end,
>> make_fun(Operator, Operands, F2).
>>
>> When I call it as:
>> F1 = make_fun(plus, lists:seq(1,10), fun() -> 0 end).
>>
>> Is F1 same as F2 below ?
>> F2 = fun() -> 1 + 2 +
>> fun() -> 3 + 4 +
>> fun() -> 5 + 6 +
>> fun() -> 7 + 8 +
>> fun() -> 9 + 10 +
>> fun() -> 0 end()
>> end()
>> end()
>> end()
>> end()
>> end.
>
>
> No, F1 is not the same as F2. A function F is a function definition, then
> F() is a function application. The F1 shell be expand as
>
> (fun() ->
> 9 + 10 +
> (fun() ->
> 7 + 8 +
> (fun() ->
> 5 + 6 +
> (fun() ->
> 3 + 4 +
> (fun() ->
> 1 + 2 + (fun() -> 0 end)()
> end)()
> end)()
> end)()
> end)()
> end)
>
> All F() evaluates itself, but F doesn't. Functions applied can be reduced,
> and F1 is reduced as a form
>
> (fun() ->
> 9 + 10 +
> (7 + 8 +
> (5 + 6 +
> (3 + 4 +
> (1 + 2 + 0)
> ) ) )
> end)
>
> Note that it cannot be a function with any binary operator + accompanied
> by a function definition. For example, try to write a program with you
> make_fun/3 definition, and make the F1 function in Erlang shell. And
> give following instructions:
>
> F3 = fun()-> 1 + 2 + F1 end, F3().
>
> You will get a bad argument error in arithmetic expression. Obviously
> in your make_fun/3, every time it make a fun() -> end expression,
> it evaluates a preceding function and puts the result as an operand of +,
> and the preceding function is not a function definition any more.
Hi Yau-Hsien,
It seems like not. For example, below example indicates F is not
evaluated when constructing F2.
1> F = fun() -> blah end.
#Fun<erl_eval.20.21881191>
2> F2 = fun() -> 1 + 2 + F() end.
#Fun<erl_eval.20.21881191>
3> F2().
** exception error: bad argument in an arithmetic expression
in operator +/2
called as 3 + blah
I also checked core file of sample code, using 'to_core' option, and the code:
18 fun() -> 9 + 10 +
19 fun() -> 0 end()
20 end()
is translated to:
%% Line 18
( fun () ->
let <_cor0> =
%% Line 19
( fun () ->
0
-| [{'id',{2,100470014,'-make_fun2/0-fun-0-'}}] )
in let <_cor1> =
%% Line 19
apply _cor0
()
in call 'erlang':'+'
(19, _cor1)
-| [{'id',{3,119737161,'-make_fun2/0-fun-1-'}}] )
It defines <_cor0>, as fun() -> 0 end, then doing 'apply _cor0'. So
It's calling fun _cor0.
Yoshihiro
>
>>
>> Also, is there any difference between funs that are defined at runtime
>> and funs that are defined at compile time in terms of how they are
>> executed ?
>>
>> Thank you
>> Yoshihiro
>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>
>
>
>
> --
>
> Best Regards.
>
> --- Y-H. H.
>
>
More information about the erlang-questions
mailing list