www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is this a bug or feature?

reply Li Jie <cpunion gmail.com> writes:
Code:

# import std.gc;
#
# class Foo{
#   private:
#   int value = 3;
#
#   public:
#   ~this(){
#       writefln("call destructor");
#   }
#
#   void delegate() foo(){
#       return delegate void(){
#           writefln(value);
#       };
#   }
# }
#
# void main(){
#   void delegate() dg = (new Foo).foo;
#   std.gc.fullCollect();
#   dg();
# }

I expect it output "3", but the output is a big number, not "3".

If comment std.gc.fullCollect(), it output "3", and it is right.

I think a closure must save all contexts, isn't it?
Jan 15 2007
parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Li Jie wrote:
 Code:
 
 # import std.gc;
 #
 # class Foo{
 #   private:
 #   int value = 3;
 #
 #   public:
 #   ~this(){
 #       writefln("call destructor");
 #   }
 #
 #   void delegate() foo(){
 #       return delegate void(){
 #           writefln(value);
 #       };
 #   }
 # }
 #
 # void main(){
 #   void delegate() dg = (new Foo).foo;
 #   std.gc.fullCollect();
 #   dg();
 # }
 
 I expect it output "3", but the output is a big number, not "3".
 
 If comment std.gc.fullCollect(), it output "3", and it is right.
 
 I think a closure must save all contexts, isn't it?

D does not have true closures. If the stack frame of the enclosing function is invalidated, then all bets are off. In Foo.foo above, the 'value' variable is a member of the 'this' reference. When Foo.foo returns, that delegate literal's context pointer is invalidated, and (therefore) so is the 'this' reference. If you want a delegate with a more persistent context, you must use a delegate to a member function, as in: class Foo { int value = 3; ~this() { writefln("dtor"); } void foo() { writefln(value); } } void main() { // Note the '&' void delegate() dg = &(new Foo).foo; std.gc.fullCollect(); dg(); } -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Jan 16 2007
next sibling parent reply BCS <ao pathlink.com> writes:
Reply to Kirk,

 Li Jie wrote:
 

 D does not have true closures. If the stack frame of the enclosing
 function is invalidated, then all bets are off.
 
 In Foo.foo above, the 'value' variable is a member of the 'this'
 reference. When Foo.foo returns, that delegate literal's context
 pointer is invalidated, and (therefore) so is the 'this' reference.
 
 If you want a delegate with a more persistent context, you must use a
 delegate to a member function, as in:
 
 class Foo {
 int value = 3;
 ~this() { writefln("dtor"); }
 void foo() {
 writefln(value);
 }
 }
 void main() {
 // Note the '&'
 void delegate() dg = &(new Foo).foo;
 std.gc.fullCollect();
 dg();
 }

What I would like to see is "scoped" delegate literals. This would let you make a delegate literal and say what pointer to use for the context. My choice for a syntax would be allowing delegates as dot operators on object references and other pointers. class Foo { int value = 3; int delegate() foo() { return this.{return value;}; } }
Jan 16 2007
parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
BCS wrote:
 Reply to Kirk,
 
 Li Jie wrote:

 D does not have true closures. If the stack frame of the enclosing
 function is invalidated, then all bets are off.

 In Foo.foo above, the 'value' variable is a member of the 'this'
 reference. When Foo.foo returns, that delegate literal's context
 pointer is invalidated, and (therefore) so is the 'this' reference.

 If you want a delegate with a more persistent context, you must use a
 delegate to a member function, as in:

 class Foo {
 int value = 3;
 ~this() { writefln("dtor"); }
 void foo() {
 writefln(value);
 }
 }
 void main() {
 // Note the '&'
 void delegate() dg = &(new Foo).foo;
 std.gc.fullCollect();
 dg();
 }

What I would like to see is "scoped" delegate literals. This would let you make a delegate literal and say what pointer to use for the context. My choice for a syntax would be allowing delegates as dot operators on object references and other pointers. class Foo { int value = 3; int delegate() foo() { return this.{return value;}; } }

Method literals, eh? Nifty. -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Jan 16 2007
parent BCS <ao pathlink.com> writes:
Reply to Kirk,

 BCS wrote:

 Method literals, eh? Nifty.

Not just methods: int[] foo; (&foo).{ int ret = 0; foreach(int i; *this) ret += i; return ret; } maybe even anything that can fit int a size_t (byte, short, int) Why not interface literals? interface I { int foo(); } struct S { int i; } auto a = new S; I i = s.I // I don't like the syntax, but... { int foo() { return this.i; } } Of course this requiters that interfaces be re implemented using context/v-table pairs, but that is an old soap-box.
Jan 16 2007
prev sibling parent reply %u <u fearof.spm> writes:
== Quote from Kirk McDonald (kirklin.mcdonald gmail.com)'s article
 If you want a delegate with a more persistent context
      void foo() {

Doesn't this solution only work because the newed and collected memory is not overwritten? Therefore "more persistent" only means until it is overwritten? Shouldn't one code
      static void foo() {

Jan 16 2007
parent BCS <ao pathlink.com> writes:
Reply to %u,

 == Quote from Kirk McDonald (kirklin.mcdonald gmail.com)'s article
 
 If you want a delegate with a more persistent context void foo() {
 

is not overwritten? Therefore "more persistent" only means until it is overwritten? Shouldn't one code
 static void foo() {
 


A delegate is a context/function pointer pair. There for, as long as you keep the delegate around, the Foo won't get collected.
Jan 16 2007