Thread overview
How to make delegate refer to itself?
Nov 23, 2013
H. S. Teoh
Nov 23, 2013
lomereiter
Nov 24, 2013
Ary Borenszweig
Nov 24, 2013
Ali Çehreli
Nov 24, 2013
bearophile
November 23, 2013
How do I make a delegate refer to itself? I'm running into a chicken-and-egg problem where a delegate needs to remove itself from an event queue, but I don't know how to make it refer to itself:

	queue.register((Event e) {
		if (e == ...)
			queue.remove( /* ??? how to refer to self? */ );
	});

I tried this workaround but it still doesn't work:

	auto dg = (Event e) {
		if (e == ...)
			queue.remove(dg); // NG: Compiler complains 'dg' isn't defined
	};
	queue.register(dg);

I thought the auto was the problem, so I changed it to an explicit type, but still no cigar:

	void delegate(Event) dg = (Event e) {
		if (e == ...)
			queue.remove(dg); // NG: Still complains 'dg' isn't defined
	};
	queue.register(dg);


T

-- 
Heuristics are bug-ridden by definition. If they didn't have bugs, they'd be algorithms.
November 23, 2013
Why so much fuss about delegates? I would simply define an interface.

// factory function for simple cases
queue.register(eventHandler((Event e) { ... }));

// here, 'this' is available
class SomeComplicatedHandler : IEventHandler { ... }


November 24, 2013
On 11/23/13 7:57 PM, H. S. Teoh wrote:
> void delegate(Event) dg = (Event e) {
> 		if (e == ...)
> 			queue.remove(dg); // NG: Still complains 'dg' isn't defined
> 	};

Split it in declaration and initialization:

void delegate(Event) dg;
dg = (Event e) {
	if (e == ...)
		queue.remove(dg);
};

November 24, 2013
On 11/23/2013 02:57 PM, H. S. Teoh wrote:
> How do I make a delegate refer to itself? I'm running into a
> chicken-and-egg problem where a delegate needs to remove itself from an
> event queue, but I don't know how to make it refer to itself:
>
> 	queue.register((Event e) {
> 		if (e == ...)
> 			queue.remove( /* ??? how to refer to self? */ );
> 	});
>
> I tried this workaround but it still doesn't work:
>
> 	auto dg = (Event e) {
> 		if (e == ...)
> 			queue.remove(dg); // NG: Compiler complains 'dg' isn't defined
> 	};
> 	queue.register(dg);
>
> I thought the auto was the problem, so I changed it to an explicit type,
> but still no cigar:
>
> 	void delegate(Event) dg = (Event e) {
> 		if (e == ...)
> 			queue.remove(dg); // NG: Still complains 'dg' isn't defined
> 	};
> 	queue.register(dg);
>
>
> T
>
Timon Gehr's improvement of the Y combinator:

  http://forum.dlang.org/post/l55gr6$1ltp$1@digitalmars.com

import std.stdio;

alias Event = int;

struct Q
{
    void register(void delegate(Event) dg)
    {
        writeln("register()");
        dg(42);
    }

    void remove(void delegate(Event))
    {
        writeln("removing");
    }
}

auto y(S,T...)(S delegate(T) delegate(S delegate(T)) f){
    struct F{ S delegate(T) delegate(F) f; alias f this; }
    return (x=>x(x))(F(x=>f((T v)=>x(x)(v))));
}

void main()
{
    auto queue = Q();

    auto dg = y((void delegate(Event e) self) =>
        (Event e) {
            if (true)
                queue.remove(self);
        });
    queue.register(dg);
}

Of course, you don't need main.dg.

Ali

November 24, 2013
Ali Çehreli:

> Timon Gehr's improvement of the Y combinator:
>
>   http://forum.dlang.org/post/l55gr6$1ltp$1@digitalmars.com

Nice, I will update the Rosettacode page.

Bye,
bearophile