January 31, 2017
On Tuesday, 31 January 2017 at 06:32:02 UTC, Ali Çehreli wrote:
> On 01/30/2017 08:12 PM, Profile Anaysis wrote:
>>
>> import std.stdio, std.concurrency, core.thread;
>>
>> class Search : Fiber
>> {
>>     this() { super(&start); }
>>     int res = 0;
>>     void start()
>>     {
>>     Fiber.yield();
>>         res = 1;
>>     }
>> }
>>
>> void main()
>> {
>>
>>     auto search = new Search();
>>
>>     search.call(); writeln(search.res);
>>     search.call(); writeln(search.res);
>>     search.call(); writeln(search.res); // crashes after 3rd call(first
>> two work fine)
>> }
>
> That's because the fiber is not in a callable state. (You can check with search.state.) Here is one where the fiber function lives (too) long:
>
> import std.stdio, std.concurrency, core.thread;
>
> class Search : Fiber
> {
>     this() { super(&start); }
>     int res = 0;
>     void start() {
>         while (true) {
>             Fiber.yield();
>             ++res;
>         }
>     }
> }
>
> void main()
> {
>     auto search = new Search();
>
>     foreach (i; 0 .. 5) {
>         search.call();
>         writeln(search.res);
>     }
> }
>
> Ali

Just curious, how can I use start() recursively?

I would like to iterate over a recursive structure and yield for each "solution". I could use a stack to store the values but the whole point of the fiber was to avoid that.


void start() {
   while (true) {
      Fiber.yield();
      ++res;
   }
}


Seems I can't create start with a parameter and non-void return type. This seems to make it about useless to use a fiber recursively because no pushing and popping on the stack occur.

class Search : Fiber
{
    this() { super(&start); }
    bool End = false;

    int res = 0;

    void start() {
        while (!End) 		
		{
			
			int Foo(int x)
			{
				Fiber.yield();
				if (x < 10)
				{
					res = Foo(x++);
					return res;
				}
				else
					return x;
				
			}
			
			
        }
    }


void main()
{

	auto search = new Search();
	foreach (i; 0 .. 5)
	{
         search.call();
         writeln(search.res);
	}


	search.End = true;
}


My goal is simple, to yield a solution at each step in the recursive process.

Maybe I can use another fiber using the lambda syntax?
January 31, 2017
On 01/31/2017 03:00 AM, Profile Anaysis wrote:

> Just curious, how can I use start() recursively?
[...]
> Seems I can't create start with a parameter and non-void return type.

Options:

- The class can maintain state

- You can start the fiber with a delegate;

    int local;
    double state;
    () => foo(local, state)

Other than the entry point, there is no requirement in what you can do. The following code yields inside a recursive function:

import std.stdio, std.concurrency, core.thread;

class Search : Fiber
{
    int state;

    this(int state) {
        this.state = state;
        super(&start);
    }
    int res = 0;
    void start() {
        recursive(state);
    }

    void recursive(int s) {
        if (s == 0) {
            return;
        }
        res = s;
        Fiber.yield();
        recursive(s - 1);
    }
}

void main()
{
    auto search = new Search(42);

    foreach (i; 0 .. 5) {
        search.call();
        writeln(search.res);
    }
}

Ali

January 31, 2017
On Tuesday, 31 January 2017 at 11:31:28 UTC, Ali Çehreli wrote:
> On 01/31/2017 03:00 AM, Profile Anaysis wrote:
>
> > [...]
> [...]
> > [...]
> return type.
>
> Options:
>
> [...]

Thanks again!
January 31, 2017
On Monday, 30 January 2017 at 11:03:52 UTC, Profile Anaysis wrote:
> I need to yield from a complex recursive function too allow visualizing what it is doing.
>
> e.g., if it is a tree searching algorithm, I'd like to yield for each node so that the current state can be shown visually.
>
> I realize that there are several ways to do this but D a yield version without additional threads would be optimal. I don't need concurrency or speed, just simple.

Sounds like opApply (external iteration) may well be the way to go.
It is a great tool to separate (possibly complex) iteration logic from (possibly complex) instance processing logic.
Here is a random recipe: https://www.sociomantic.com/blog/2010/06/opapply-recipe

An example:

-----
import std.stdio;

class Node {
	int value;
	Node left, right;
	this (int value_) {value = value_;}
}

struct InOrderViewer {
	Node root;
	int opApply (int delegate (Node) process) {
		void recur (Node cur) {
			if (cur is null) return;
			recur (cur.left);
			process (cur); // use return value here to allow break in foreach
			recur (cur.right);
		}
		recur (root);
		return 0;
	}
}

void main () {
	auto v1 = new Node (1);
	auto v2 = new Node (2);
	auto v3 = new Node (3);
	auto v4 = new Node (4);
	auto v5 = new Node (5);
	v2.left = v1;
	v2.right = v5;
	v5.left = v3;
	v3.right = v4;

	foreach (node; InOrderViewer (v2)) {
		writeln (node.value ^^ 2); // 1 4 9 16 25
	}
}
-----

Ivan Kazmenko.

1 2
Next ›   Last »