Erlang/OTP Forums

Author Message

<  Erlang  ~  can anyone explain how this code work?

porkai
Posted: Sat Jul 18, 2009 9:47 pm Reply with quote
Joined: 18 Jul 2009 Posts: 1
I am reading Joe Armstrong thesis and found the following code. I am very new to Erlang and have huge difficulty in adusting to it (used to C#/Java those type of lang but not funcitonal) .. so any help will be very helpful:

This is his version of factorial:
Fact=fun(X)-> G=fun(0,F) ->1;
(N,F)->N*F(N-1,F)
end,
G(X,G)
end.

then a Fact(4) shall evaluate to 24 .

But i ahve trouble tracing it. and diassemble the technique piece by piece
View user's profile Send private message
Mazen
Posted: Sun Jul 19, 2009 10:33 am Reply with quote
User Joined: 20 Jul 2006 Posts: 164 Location: London
Code:

Fact =
  fun(X) ->
    G = fun(0, F) ->
              1;
           (N, F) ->
              N * F(N-1, F)
        end,
    G(X, G)
  end.


Fact is a fun which takes 1 integer argument, this fun then defines another fun G which takes two arguments, one integer and a fun. Then this fun (the G fun) is called with the value passed to Fact (the integer X) and itself (the G fun). if the integer is 0, then 1 is returned to who ever called the G fun. If the integer is other then zero then the value of X is multiplied with the result of F(). Now F is what ever fun was passed on to G which in this case is itself G thus it is recursive. G is defined once, and used inside itself.

Another example of this code would look something like:

Code:
 
fact(X) ->
  g(X).
 
g(0) ->
  1;
g(N) ->
  N * g(N-1).


Joe's way of writing it with funs is probably to illustrate that it can be done and give a "wow" or "coolness" factor to it. not exactly production code imho, but nevertheless has a nice twist to it Smile
View user's profile Send private message
baryluk
Posted: Tue Aug 18, 2009 10:02 am Reply with quote
User Joined: 05 Aug 2009 Posts: 48
There is even something called y-combinator, it is an fixed-point operator for recursive function:

Code:

y(M) ->
    G = fun (F) -> M(fun(A) -> (F(F))(A) end) end,
    G(G).

Then you can just use it like this:

Code:

Fact = y(fun (Me) ->
             fun(0) -> 1;
                (N) -> N * Me(N-1)
             end
        end).


And use it:
Code:

Fact(10).


It takes few days to understand it completly. Smile
View user's profile Send private message
jmontelius
Posted: Sat Oct 03, 2009 8:39 am Reply with quote
User Joined: 07 Mar 2009 Posts: 29
To understand what we are trying to do it could be good to understand what we want to do but can not. This is how it could have been:
Code:

Fac = fun(0) ->
              1;
           (N) ->
              N * Fac(N-1)
      end.


The scoping rules in Erlang does not allow us to use the Fac variable inside the expression. Many other functional and logical programming langues have no problem with this but it is not allowed in Erlang.

So the trick that is applied is to make the function take an extra argument and pass the function as an argument when we call it. Joe's code is thus a clever work-around to be able to do something that is not there at first glance.

You might wonder why the scoping ruleas are not changed. We'll that would also allow us to do things like

Code:

X = [foo|X]


This does of course looks fun and any Prolog programmer could tell you that it's quite useful. If you ask the people that implement the garbage collector and message passing rutines they would probably throw bricks on you if you proposed something like this.
View user's profile Send private message

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum