www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Can a member function return a delegate to itself?

reply Steve Teale <steve.teale britseyeview.com> writes:
Something like:

class Foo
{
    int a;

    this() { a = 0; }

    void delegate(int) sum(int n) 
              { a += n; return cast(void delegate(int)) &this.sum; }
}
May 22 2007
next sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Steve Teale wrote:
 Something like:
 
 class Foo
 {
     int a;
 
     this() { a = 0; }
 
     void delegate(int) sum(int n) 
               { a += n; return cast(void delegate(int)) &this.sum; }
 }
Yes, although you don't need the cast(). -- Chris Nicholson-Sauls
May 23 2007
prev sibling next sibling parent davidl <davidl 126.com> writes:
why would u need this ?
and imo D is not capable of doing so cause the return type of such a  
function
is not defined.





-- 
使用 Opera 革命性的电子邮件客户程序: http://www.opera.com/mail/
May 23 2007
prev sibling next sibling parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Steve Teale wrote:
 Something like:
 
 class Foo
 {
     int a;
 
     this() { a = 0; }
 
     void delegate(int) sum(int n) 
               { a += n; return cast(void delegate(int)) &this.sum; }
 }
As said this can't be done because the return type of such a function would be it's own type, and so any description of the type would need to include itself as a (strict) substring. A type that cannot be described cannot be used. However, there's a workaround: --- class Foo { int a; this() { a = 0; } // you can also put this into a struct member named "sum" // if you prefer Foo opCall(int n) { a += n; return this; } alias opCall sum; // optional } // test code: import std.stdio; void main() { scope foo = new Foo; foo.sum(1)(2)(3); writefln(foo.a); // writes '6' } --- (also popular with structs instead of classes. Or struct members of classes)
May 23 2007
prev sibling next sibling parent reply BCS <BCS pathlink.com> writes:
Steve Teale wrote:
 Something like:
 
 class Foo
 {
     int a;
 
     this() { a = 0; }
 
     void delegate(int) sum(int n) 
               { a += n; return cast(void delegate(int)) &this.sum; }
 }
as mentioned, the reason this isn't directly doable is that the type is undefinable. However this is strictly a limitation of the D Syntax and their is no problem with actually doing it if you can tell DMD how. I have does this using typing tricks before: struct S { S delegate(int,int) dg; } struct O { int k; S go(int i, int j) { O* o = new O o.k = k+i+j; S ret; ret.dg = &o.go; return ret; } }
May 23 2007
next sibling parent reply Gregor Richards <Richards codu.org> writes:
BCS wrote:
 as mentioned, the reason this isn't directly doable is that the type is 
 undefinable. However this is strictly a limitation of the D Syntax and 
 their is no problem with actually doing it if you can tell DMD how. I 
 have does this using typing tricks before:
 
 
 struct S
 {
     S delegate(int,int) dg;
 }
 
 struct O
 {
     int k;
     S go(int i, int j)
     {
         O* o = new O
         o.k = k+i+j;
         S ret;
         ret.dg = &o.go;
         return ret;
     }
 }
I just want to say that this method is brilliant. It's easy to read and understand on a high and low level, and does everything you need it to do with no questions asked. Bravo. - Gregor Richards
May 23 2007
parent BCS <BCS pathlink.com> writes:
Gregor Richards wrote:
 BCS wrote:
 
 as mentioned, the reason this isn't directly doable is that the type 
 is undefinable. However this is strictly a limitation of the D Syntax 
 and their is no problem with actually doing it if you can tell DMD 
 how. I have does this using typing tricks before:


 struct S
 {
     S delegate(int,int) dg;
 }

 struct O
 {
     int k;
     S go(int i, int j)
     {
         O* o = new O
         o.k = k+i+j;
         S ret;
         ret.dg = &o.go;
         return ret;
     }
 }
I just want to say that this method is brilliant. It's easy to read and understand on a high and low level, and does everything you need it to do with no questions asked. Bravo. - Gregor Richards
A simple thank you would suffice. <g> Your welcome.
May 23 2007
prev sibling parent reply teales <steve.teale britseyeview.com> writes:
BCS Wrote:

 Steve Teale wrote:
 Something like:
 
 class Foo
 {
     int a;
 
     this() { a = 0; }
 
     void delegate(int) sum(int n) 
               { a += n; return cast(void delegate(int)) &this.sum; }
 }
as mentioned, the reason this isn't directly doable is that the type is undefinable. However this is strictly a limitation of the D Syntax and their is no problem with actually doing it if you can tell DMD how. I have does this using typing tricks before: struct S { S delegate(int,int) dg; } struct O { int k; S go(int i, int j) { O* o = new O o.k = k+i+j; S ret; ret.dg = &o.go; return ret; } }
I also think your solution is nifty. So the answer to my question is rather like what you suggested, but you have to add an opCall to S, as in: import std.stdio; struct S { S delegate(int) dg; S opCall(int n) { dg(n); return *this; } } struct O { int a; S sum(int i) { a += i; S ret; return ret; } } void main(char[][] args) { O o; o.sum(1)(2)(3); writefln("%d", o.a); // prints 6 as desired } It was just a curious question in the first place but you never know, somebody might find a use for it.
May 23 2007
next sibling parent teales <steve.teale britseyeview.com> writes:
teales Wrote:

 BCS Wrote:
 
 Steve Teale wrote:
 Something like:
 
 class Foo
 {
     int a;
 
     this() { a = 0; }
 
     void delegate(int) sum(int n) 
               { a += n; return cast(void delegate(int)) &this.sum; }
 }
as mentioned, the reason this isn't directly doable is that the type is undefinable. However this is strictly a limitation of the D Syntax and their is no problem with actually doing it if you can tell DMD how. I have does this using typing tricks before: struct S { S delegate(int,int) dg; } struct O { int k; S go(int i, int j) { O* o = new O o.k = k+i+j; S ret; ret.dg = &o.go; return ret; } }
I also think your solution is nifty. So the answer to my question is rather like what you suggested, but you have to add an opCall to S, as in: import std.stdio; struct S { S delegate(int) dg; S opCall(int n) { dg(n); return *this; } } struct O { int a; S sum(int i) { a += i; S ret; return ret; } } void main(char[][] args) { O o; o.sum(1)(2)(3); writefln("%d", o.a); // prints 6 as desired } It was just a curious question in the first place but you never know, somebody might find a use for it.
Hmm, interesting, the system converted ret.dg = & s u m ; (ignore the spaces) to the math summation character
May 23 2007
prev sibling parent BCS <ao pathlink.com> writes:
Reply to teales,

 I also think your solution is nifty. So the answer to my question is
 rather like what you suggested, but you have to add an opCall to S, as
 in:
 
 import std.stdio;
 
 struct S
 {
 S delegate(int) dg;
 S opCall(int n) { dg(n); return *this; }
 }
 struct O
 {
 int a;
 S sum(int i)
 {
 a += i;
 S ret;

 return ret;
 }
 }
 void main(char[][] args)
 {
 O o;
 o.sum(1)(2)(3);
 writefln("%d", o.a); // prints 6 as desired
 }
 It was just a curious question in the first place but you never know,
 somebody might find a use for it.
 
I'd skipp the opCall step and do that as
 o.sum(1).dg(2).dg(3);
The use I'v found for it is in state mechines S s; while(s.go) s=s.dg(input);
May 24 2007
prev sibling parent Manfred Nowak <svv1999 hotmail.com> writes:
Steve Teale wrote

 Something like:
     void delegate(int) sum(int n) 
               { a += n; return cast(void delegate(int)) &this.sum; }
might work with an auxiliary type definition `Th': import std.stdio; typedef T delegate() Th; typedef Th delegate() T; T g, h; T f(){ writefln( "returning own type"); return g; } void main(){ h= f(); } -manfred
May 23 2007