0

This is probably easy for someone with experience in Erlang but I have none. Im trying to make a fibonacci tree of processes. It shall then accept a message where i can calculate the sum of all nodes under the one im passing it to.

create_fibtree(N) when N > 1 ->
Child1 = spawn(fun() -> create_fibtree(N-1) end),
Child2 = spawn(fun() -> create_fibtree(N-2) end),

receive 
    Sum ->
        Child1 ! sum + 1,
        Child2 ! sum + 1,
        io:format ("sum is ~p.~n", [Sum])
end;
create_fibtree(N) when N =< 1 ->
    ok.

When i run this:

c(fib_tree2).
{ok,fib_tree2}
2> fib_tree2:create_fibtree(10).

the Erlang console hangs. Cant figure out why but its something with the receive clause right?

And yes this is an homework, my teacher isn't there this week, that's why im looking for stand ins on the internet.

nilsi
  • 10,351
  • 10
  • 67
  • 79
  • 2
    Well, I am usually replying in e-mails, usually in less than an hour from the moment they are sent...! Emil's answer is on the right direction. I am not certain about stackoverflow's policy on homework questions however. – aronisstav Nov 19 '12 at 22:52
  • aronisstav, [How to ask and answer homework questions?](http://meta.stackexchange.com/questions/10811/how-to-ask-and-answer-homework-questions) As long as the question is on-topic we should try to answer it, imo. Note that I in my answer tried to avoid anything which would create a cheating situation. – Emil Vikström Dec 02 '12 at 12:27

2 Answers2

2

You need to have a first message. Since I also have the assignment I can chip in with some hints:

  • Try to separate the tree creation from the sum calculation. Create the tree and then move over into another function where you receive and send messages.

  • Someone must send a message before you can receive it.

  • You seems to be confused about which direction the messages are passed. You should probably send one message down the tree (to tell your children that you are counting the nodes) and another upwards in the tree (the result from each node). Here is a suggestion for an algorithm:

In each node:

  1. Send a message {get_sum, Id, Pid} to both children, where Id is some random unique identifier, e.g., from the now/0 function and Pid is from self/0.
  2. Receive exactly two answers (one from each child) on the form {sum, Id, Sum} (where Id is the same as before).
  3. The two sums are added and you add 1 for the current node.
  4. Send the answer back up to the parent in the tree.

Check out the Erlang debugger which is great for troubleshooting this type of things:

> c(modulename, [debug_info]).
> debugger:start().
(Module -> Interpret -> Pick the .erl file for the module you just compiled)
Emil Vikström
  • 90,431
  • 16
  • 141
  • 175
  • Thank you for the hint's, really appreciated. Nice too have some inputs from others that did the same exercise. I ended up using some message passing for the sum without the Id that you suggested. Will take a look at the Erlang debugger, seems like a nice tool. – nilsi Nov 21 '12 at 13:16
  • 1
    Another interesting aspect would be how to solve this with an generic server. Something that i tried but didn't manage to finish – nilsi Nov 21 '12 at 13:23
1

Right, the receive clause blocks the function as it never receives any messages. But this code in general is not a very good way to compute the fib numbers. It can be done with a simple recursive function without the need of spawning processes.

P.S. Child1 ! sum + 1, will fail, as you try to add atom and integer

  • But shall it not wait on the receive clause until it gets a message? Still dosent understand why it hangs.Im spawning processes cause it says so in the exercise. – nilsi Nov 19 '12 at 22:14
  • It waits for a message but as you run the function in the main process (i.e. from the shell) it blocks it, try this instead: Pid = spawn(module,create_fibtree, [10]), Pid ! 10. –  Nov 19 '12 at 22:14