www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - delegate, template and alias

reply Heromyth <bitworld qq.com> writes:
I have a delegate as a parameter in a function which is a template function.
And I want to use alias for the delegate parameter.
Is there a better way for this?

My demo code:

template AsynchronousAction(T)
{
	alias void delegate(T argument) FuncType;
}

public class TestC
{
	int b = 3;

	//void test(T)(void delegate(T argument) func )
	void test(T)(AsynchronousAction!(T).FuncType func )
	{
		static if(is(T == string))
		func("It's me");
	}

	this(int x)
	{
		b = x;
	}
}
Dec 18 2011
next sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Dec 18, 2011 at 14:13, Heromyth <bitworld qq.com> wrote:
 I have a delegate as a parameter in a function which is a template function.
 And I want to use alias for the delegate parameter.
 Is there a better way for this?

I suppose you do *not*want the commented line? You can extract a template parameter with an is() expression. But the extracted type is only accessible inside a static if. Solution: expose it through an alias: template AsynchronousActionParam(T) { static if (is(T t == void delegate(U), U)) alias U AsynchronousActionParam ; else static assert(false, "Bad AsynchronousActionParam call: " ~ T.stringof); } class TestC { int b = 3; void test(F)(F func ) if (is(AsynchronousActionParam!F)) { static if (is(AsynchronousActionParam!F == string)) func("It's me"); else writeln("test called with void delegate(" ~ AsynchronousActionParam!F ~ ")."); } this(int x) { b = x; } } void main() { auto c = new TestC(3); void foo(string s) { writeln("foo: ", s);} c.test(&foo); }
Dec 18 2011
parent reply Heromyth <bitworld qq.com> writes:
== Quote from Philippe Sigaud (philippe.sigaud gmail.com)'s article
 On Sun, Dec 18, 2011 at 14:13, Heromyth <bitworld qq.com> wrote:
 I have a delegate as a parameter in a function which is a template function.
 And I want to use alias for the delegate parameter.
 Is there a better way for this?

You can extract a template parameter with an is() expression. But the extracted type is only accessible inside a static if. Solution: expose it through an alias: template AsynchronousActionParam(T) { static if (is(T t == void delegate(U), U)) alias U AsynchronousActionParam ; else static assert(false, "Bad AsynchronousActionParam call: " ~ T.stringof); } class TestC { int b = 3; void test(F)(F func ) if (is(AsynchronousActionParam!F)) { static if (is(AsynchronousActionParam!F == string)) func("It's me"); else writeln("test called with void delegate(" ~ AsynchronousActionParam!F ~ ")."); } this(int x) { b = x; } } void main() { auto c = new TestC(3); void foo(string s) { writeln("foo: ", s);} c.test(&foo); }

Thanks greatly. Your code makes me understanding D's template much more. The template in D is so amazing.
             writeln("test called with void delegate(" ~
 AsynchronousActionParam!F ~ ").");

writeln("test called with void delegate(" ~ AsynchronousActionParam!F.stringof ~ ").");
 I suppose you do *not*want the commented line?

I want to convert a delegate type define in C# to D's, as such: public delegate void AsynchronousAction<T>(T argument, AsyncContinuation asyncContinuation); public static void ForEachItemSequentially<T>(IEnumerable<T> items, AsyncContinuation asyncContinuation, AsynchronousAction<T> action) { ...... }
Dec 19 2011
parent reply Heromyth <bitworld qq.com> writes:
== Quote from Heromyth (bitworld qq.com)'s article
 == Quote from Philippe Sigaud (philippe.sigaud gmail.com)'s article
 I suppose you do *not*want the commented line?

public delegate void AsynchronousAction<T>(T argument, AsyncContinuation asyncContinuation); public static void ForEachItemSequentially<T>(IEnumerable<T> items, AsyncContinuation asyncContinuation, AsynchronousAction<T> action) { ...... }

Woo, I got it. template AsynchronousAction(T) { alias void delegate(T argument) AsynchronousAction; } public class TestC { int b = 3; //void test(T)(void delegate(T argument) func ) void test(T)(AsynchronousAction!(T) func ) { static if(is(T == string)) func("It's me"); } this(int x) { b = x; } }
Dec 19 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/19/2011 06:46 PM, Philippe Sigaud wrote:
 On Mon, Dec 19, 2011 at 15:35, Heromyth<bitworld qq.com>  wrote:
 Woo, I got it.

What's the difference with your first post?

He uses an eponymous template now.
Dec 19 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/19/2011 09:30 PM, Philippe Sigaud wrote:
 On Mon, Dec 19, 2011 at 18:49, Timon Gehr<timon.gehr gmx.ch>  wrote:
 On 12/19/2011 06:46 PM, Philippe Sigaud wrote:
 On Mon, Dec 19, 2011 at 15:35, Heromyth<bitworld qq.com>    wrote:
 Woo, I got it.

What's the difference with your first post?

He uses an eponymous template now.

Ah yes, thanks. Strange, I'm pretty sure I used the eponymous trick and it didn't work, for some reason. Anyway, Heromyth, I'm slowly working on a D template tutorial. The current pdf is at: https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/dtemplates.pdf (click on View Raw to download). It's still incomplete. I'll work on it during the holidays and post on D.announce to get some feedback on it, but you're welcome if you want to give it a try. Philippe

Looks very good. Knowing it is a work in progress, I will already give some feedback: You have a typo on page 15: static if (is(T t = U[], U)) // is T an array of U, for some type U? You probably meant to write static if (is(T t == U[], U)) // is T an array of U, for some type U? On page 18, I think your explanation why you used .power instead of power is not yet entirely accurate. The only reason why it is needed is because you are defining an eponymous template that hides the global template. Also on page 18: 'Note that this template will work not only for unary (one argument) functions but also for n-args functions,' The implementation given does not work for n-args functions because functions cannot return a tuple. Page 23: 'Note that flatten works perfectly on ranges too, but is not lazy' Ranges don't have the concatenation operator, so it will not work. Page 25: 'And due to (to my eyes) a bug in alias, you cannot alias them to a symbol: alias (a){ return a;} Id; // Error' It is a restriction that the current D grammar has. You can do this: alias ID!((a){ return a;}) Id; where ID is template ID(alias X){alias X ID;} Page 25: 'Since they are delegates, they can capture local symbols, as long as these are defined at compile-time:' They can even capture local symbols that don't have a compile-time value. For example: auto foo(alias s)(){return s();} void main() { int x = 2; writeln(foo!({return x;})()); // prints '2' } And the link is purely symbolic, no closures or the like are allocated. What the compiler effectively does is in the lines of this: void main() { int x = 2; auto dgliteral() { return x; } // {return x;} auto foo(){ return dgliteral(); } // foo!({return x}) writeln(foo()); // call template instance } This is one of the most powerful features of D templates: They are instantiated in the most local scope that is required for them to work. Page 38: 'By the way, strangely enough, though you cannot declare ‘pure’ templates inside functions, you can declare struct templates.' Do you want to file a bug report against this? This has bothered me a few times too. Page 39: Template this parameters are also useful to determine how the type of the this reference is qualified, (const/immutable/shared/inout) Page 67: 'mixin template Concatenate() { Tuple!(This, U) opBinary(string op, this This)(This u) if (op == "~") { return tuple(this, u); } Tuple!(U, This) opBinaryRight(string op, this This)(This u) if (op == "~") { return tuple(u, this); } }' I think what you meant was this: mixin template Concatenate() { Tuple!(This, U) opBinary(string op, this This)(U u) if (op == "~") { return tuple(this, u); } Tuple!(U, This) opBinaryRight(string op, this This)(U u) if (op == "~") { return tuple(u, this); } } Page 76: 'At the time of this writing, the limitations are mostly: no classes and no exceptions (and so, no enforce).' DMD 2.057 supports classes and exceptions in CTFE =) Page 82: I'd be careful with that table. Probably most of the ones you marked as 'No' are actually 'Yes' when doing some clever things with is(typeof())? Page 90: '34 Extending a Class' Maybe add a note that this does not work across module boundaries and therefore has not much practical use. Page 90: 'return; // or return void;' That looks like it was actual syntax. Page 94/95: 'Strangely, you can only use it with the is(Type identifier, ...) syntax: you must have identifier.' 'For me, the main limitation is that template tuple parameters are not accepted. Too bad.' Do you want to file the enhancement requests, or should I file them? Having those would increase the consistency of the language. Keep up the good work!
Dec 19 2011
parent Heromyth <bitworld qq.com> writes:
== Quote from Timon Gehr (timon.gehr gmx.ch)'s article
 On 12/19/2011 09:30 PM, Philippe Sigaud wrote:
 On Mon, Dec 19, 2011 at 18:49, Timon Gehr<timon.gehr gmx.ch>  wrote:

 Anyway, Heromyth, I'm slowly working on a D template tutorial. The
 current pdf is at:

 https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/dtemplates.pdf

 (click on View Raw to download).

 It's still incomplete. I'll work on it during the holidays and post on
 D.announce to get some feedback on it, but you're welcome if you want
 to give it a try.


 Philippe

Knowing it is a work in progress, I will already give some feedback: You have a typo on page 15:

Sorry for my late post. Good job, guys.
Dec 20 2011
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Mon, Dec 19, 2011 at 15:35, Heromyth <bitworld qq.com> wrote:
 Woo, I got it.

What's the difference with your first post?
Dec 19 2011
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Mon, Dec 19, 2011 at 18:49, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 12/19/2011 06:46 PM, Philippe Sigaud wrote:
 On Mon, Dec 19, 2011 at 15:35, Heromyth<bitworld qq.com> =C2=A0wrote:
 Woo, I got it.

What's the difference with your first post?

He uses an eponymous template now.

Ah yes, thanks. Strange, I'm pretty sure I used the eponymous trick and it didn't work, for some reason. Anyway, Heromyth, I'm slowly working on a D template tutorial. The current pdf is at: https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/dtemplat= es.pdf (click on View Raw to download). It's still incomplete. I'll work on it during the holidays and post on D.announce to get some feedback on it, but you're welcome if you want to give it a try. Philippe
Dec 19 2011
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Tue, Dec 20, 2011 at 00:23, Timon Gehr <timon.gehr gmx.ch> wrote:
 Looks very good.

 Knowing it is a work in progress, I will already give some feedback:

Wow, thanks for the thorough reading! I'll correct thos points. I need to write a code extractor to automatically compile the examples, because I'm writing this after some time far away from D and I fear I'm confusing some semantics with other languages.
 Keep up the good work!

If you have the time or inclination, do not hesitate to make a pull request (examples, forgotten subjects...) Philippe
Dec 19 2011