Thread overview
Is this a bug or feature?
Jan 16, 2007
Li Jie
Jan 16, 2007
Kirk McDonald
Jan 16, 2007
BCS
Jan 17, 2007
Kirk McDonald
Jan 17, 2007
BCS
Jan 16, 2007
%u
Jan 16, 2007
BCS
January 16, 2007
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?
January 16, 2007
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
January 16, 2007
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;};
 }
}


January 16, 2007
== 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() {
January 16, 2007
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() {
>> 
> 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() {
>> 

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


January 17, 2007
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
January 17, 2007
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.