[erlang-questions] How do funs work ?

Yoshihiro Tanaka <>
Thu Mar 29 18:55:20 CEST 2012


2012/3/29 黃耀賢 (Yau-Hsien Huang) <>:
> On Wed, Mar 28, 2012 at 4:51 PM, Yoshihiro Tanaka <>
> 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
>> 
>> http://erlang.org/mailman/listinfo/erlang-questions
>
>
>
>
> --
>
> Best Regards.
>
> --- Y-H. H.
>
>



More information about the erlang-questions mailing list