1

I have been trying to implement a factorial function using the actor model with the d language. My objective is to use to create actor to calculate each part alone e spawn a new actor to make the next. I am just a beginner with D, so I'm just learning how to use the language. My objective is to expand the factorial implementation to much more. This is just a test.

Here is my problem: I'm trying to implement the factorial using recursion; the fact function will create a new fact thread for next number in line, unless it has reached the base condition.

My code:

void fact(Tid tid)
{

        int fact = 1;
        receive
        (
        (int i)
        {
            if(i == 0)
            {
                writeln("End of recursion");
            }
            else
            {
                fact *= i;
                send(thisTid, i-1);
            }
        }
    );
    send(tid, fact);
}

void main()
{

        auto tid = spawn(&fact, thisTid);
        int x = 3;
        send(tid, x);
        auto fact = receiveOnly!(int);
        writeln(fact);
}

I don't even know if that's possible, in any case it does not work. If I try to add a spwn in fact function it returns the following error:

src/main.d(62): Error: template std.concurrency.spawn does not match any function template declaration
/usr/include/x86_64-linux-gnu/dmd/phobos/std/concurrency.d(399): Error: template std.concurrency.spawn(T...) cannot deduce template function from argument types !()(int*,Tid)
src/main.d(63): Error: template std.concurrency.send does not match any function template declaration
/usr/include/x86_64-linux-gnu/dmd/phobos/std/concurrency.d(463): Error: template std.concurrency.send(T...) cannot deduce template function from argument types !()(_error_,int)

So, is it possible to do what I am trying to do? How? If not, is there any plans to make some thing like that possible?

Please, help.

jA_cOp
  • 3,275
  • 19
  • 15
Fred
  • 417
  • 6
  • 14

2 Answers2

4

I could be way off base here, but from that error message it looks to me like dmd is not using the fact that you think it is using, in your call to spawn. You have several integers named fact, and although in this (obviously cut down, since it's not 400 lines) example none of them would conflict, in the full code my guess is one of them does (because &fact would be an int* if fact was an int).

Try renaming the function to factorial or some such, and changing the spawn call where appropriate. Make sure not to change the integers.

Tim
  • 1,011
  • 6
  • 12
2

Works fine for me. What DMD version are you using? Perhaps try upgrading to 2.059 if you aren't already on it.

(Note: I say it works in that it compiles and runs. It doesn't give the write answer because fact will only receive one number before it returns, so it just returns three. You'll need to have the receive in a loop)

admin@poita ~% cat test.d
import std.stdio;
import std.concurrency;

void fact(Tid tid)
{
    int fact = 1;
    receive
    (
        (int i)
        {
            if(i == 0)
            {
                writeln("End of recursion");
            }
            else
            {
                fact *= i;
                send(thisTid, i-1);
            }
        }
    );
    send(tid, fact);
}

void main()
{
    auto tid = spawn(&fact, thisTid);
    int x = 3;
    send(tid, x);
    auto fact = receiveOnly!(int);
    writeln(fact);
}

admin@poita ~% dmd test.d
admin@poita ~% ./test
3
admin@poita ~%
Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
  • My question was about if it is some how possible to make it work. I have plan fr the future that depends on this functioning as expected. – Fred May 20 '12 at 11:10
  • Yes, it is possible to make it work. There's nothing wrong with a thread sending a message to itself, or spawning a new thread using the same function. The only problem with the code you have is that your algorithm doesn't work. – Peter Alexander May 20 '12 at 12:48
  • I cannot find the problem here and, when I try to create a new thread, it rises a template exception. I use the same call method for both calling outside and inside the function, it works outside, but does not work inside. – Fred May 20 '12 at 16:47