January 12, 2007
Lutger wrote:
> Alain wrote:
>> Frits van Bommel Wrote:
>>
>>> Alain wrote:
>>>> AddFunc addN(int n) {
>>>>     int add(int i) {
>>>>         return i + n;
>>>>     }
>>>>     return &add; // the add function captured will remember the value of n
>>>> }
>>> [snip]
>>>> Am i missing something?
>>> You shouldn't return delegates to nested functions, just like you shouldn't return pointers to local variables.
>>> Delegates to nested functions contain a pointer to the stack frame of the enclosing function. If that function has returned, the stack frame may be corrupted (especially if you have called another function, like apply(), since then).
>>
>> How come this compiles? Is it a bug ?
>>
>> Alain
> 
> This is valid code. It is up to the programmer to make sure the delegate  doesn't use vars that are out of scope. There was some talk about this, to copy the 'evironment' for later use, it might be solved in the future.
> 
> std.bind might be of use here.

As could a template.

<code>
import std .stdio ;

alias int delegate(int n) AddFunc;

template TAddN (int N) {
  const TAddN = (int i) { return i + N; } ;
}

void apply (int[] array, AddFunc func) {
  foreach (inout i; array) {
    i = func(i);
  }
}

void main () {
    int[] numbers = [1,2,3] ;

    writefln("numbers before = ", numbers);
    apply(numbers, TAddN!(40));
    writefln("numbers after = ", numbers);
}
</code>

-- Chris Nicholson-Sauls
January 12, 2007
Using DMD 1.0, I get errors on the template.

closureWithTemplate.d(19): delegate closureWithTemplate.TAddN!(40).__dgliteral2 is a nested function and cannot be accessed from main
closureWithTemplate.d(6): Error: non-constant expression __dgliteral2


  Bradley

Chris Nicholson-Sauls wrote:
> Lutger wrote:
>> Alain wrote:
>>> Frits van Bommel Wrote:
>>>
>>>> Alain wrote:
>>>>> AddFunc addN(int n) {
>>>>>     int add(int i) {
>>>>>         return i + n;
>>>>>     }
>>>>>     return &add; // the add function captured will remember the value of n
>>>>> }
>>>> [snip]
>>>>> Am i missing something?
>>>> You shouldn't return delegates to nested functions, just like you shouldn't return pointers to local variables.
>>>> Delegates to nested functions contain a pointer to the stack frame of the enclosing function. If that function has returned, the stack frame may be corrupted (especially if you have called another function, like apply(), since then).
>>>
>>> How come this compiles? Is it a bug ?
>>>
>>> Alain
>>
>> This is valid code. It is up to the programmer to make sure the delegate  doesn't use vars that are out of scope. There was some talk about this, to copy the 'evironment' for later use, it might be solved in the future.
>>
>> std.bind might be of use here.
> 
> As could a template.
> 
> <code>
> import std .stdio ;
> 
> alias int delegate(int n) AddFunc;
> 
> template TAddN (int N) {
>   const TAddN = (int i) { return i + N; } ;
> }
> 
> void apply (int[] array, AddFunc func) {
>   foreach (inout i; array) {
>     i = func(i);
>   }
> }
> 
> void main () {
>     int[] numbers = [1,2,3] ;
> 
>     writefln("numbers before = ", numbers);
>     apply(numbers, TAddN!(40));
>     writefln("numbers after = ", numbers);
> }
> </code>
> 
> -- Chris Nicholson-Sauls
January 12, 2007
Nevermind. I figured it out. The following works.

import std.stdio;

alias int delegate(int n) AddFunc;

template addN(int N) {
  AddFunc addN() {
    return delegate int (int i) { return i + N; };
  }
}

void apply (int[] array, AddFunc func) {
  foreach (inout i; array) {
    i = func(i);
  }
}

void main () {
    int[] numbers = [1,2,3] ;
    writefln("numbers before = ", numbers);
    apply(numbers, addN!(40));
    writefln("numbers after = ", numbers);
}

Bradley Smith wrote:
> Using DMD 1.0, I get errors on the template.
> 
> closureWithTemplate.d(19): delegate closureWithTemplate.TAddN!(40).__dgliteral2 is a nested function and cannot be accessed from main
> closureWithTemplate.d(6): Error: non-constant expression __dgliteral2
> 
> 
>   Bradley
> 
> Chris Nicholson-Sauls wrote:
>> Lutger wrote:
>>> Alain wrote:
>>>> Frits van Bommel Wrote:
>>>>
>>>>> Alain wrote:
>>>>>> AddFunc addN(int n) {
>>>>>>     int add(int i) {
>>>>>>         return i + n;
>>>>>>     }
>>>>>>     return &add; // the add function captured will remember the value of n
>>>>>> }
>>>>> [snip]
>>>>>> Am i missing something?
>>>>> You shouldn't return delegates to nested functions, just like you shouldn't return pointers to local variables.
>>>>> Delegates to nested functions contain a pointer to the stack frame of the enclosing function. If that function has returned, the stack frame may be corrupted (especially if you have called another function, like apply(), since then).
>>>>
>>>> How come this compiles? Is it a bug ?
>>>>
>>>> Alain
>>>
>>> This is valid code. It is up to the programmer to make sure the delegate  doesn't use vars that are out of scope. There was some talk about this, to copy the 'evironment' for later use, it might be solved in the future.
>>>
>>> std.bind might be of use here.
>>
>> As could a template.
>>
>> <code>
>> import std .stdio ;
>>
>> alias int delegate(int n) AddFunc;
>>
>> template TAddN (int N) {
>>   const TAddN = (int i) { return i + N; } ;
>> }
>>
>> void apply (int[] array, AddFunc func) {
>>   foreach (inout i; array) {
>>     i = func(i);
>>   }
>> }
>>
>> void main () {
>>     int[] numbers = [1,2,3] ;
>>
>>     writefln("numbers before = ", numbers);
>>     apply(numbers, TAddN!(40));
>>     writefln("numbers after = ", numbers);
>> }
>> </code>
>>
>> -- Chris Nicholson-Sauls
January 12, 2007
Bradley Smith wrote:
> Nevermind. I figured it out. The following works.
> 
> import std.stdio;
> 
> alias int delegate(int n) AddFunc;
> 
> template addN(int N) {
>   AddFunc addN() {
>     return delegate int (int i) { return i + N; };
>   }
> }
> 
> void apply (int[] array, AddFunc func) {
>   foreach (inout i; array) {
>     i = func(i);
>   }
> }
> 
> void main () {
>     int[] numbers = [1,2,3] ;
>     writefln("numbers before = ", numbers);
>     apply(numbers, addN!(40));
>     writefln("numbers after = ", numbers);
> }
> 
> Bradley Smith wrote:
>> Using DMD 1.0, I get errors on the template.
>>
>> closureWithTemplate.d(19): delegate closureWithTemplate.TAddN!(40).__dgliteral2 is a nested function and cannot be accessed from main
>> closureWithTemplate.d(6): Error: non-constant expression __dgliteral2
>>
>>
>>   Bradley
>>
>> Chris Nicholson-Sauls wrote:
>>> import std .stdio ;
>>>
>>> alias int delegate(int n) AddFunc;
>>>
>>> template TAddN (int N) {
>>>   const TAddN = (int i) { return i + N; } ;
>>> }
>>>
>>> void apply (int[] array, AddFunc func) {
>>>   foreach (inout i; array) {
>>>     i = func(i);
>>>   }
>>> }
>>>
>>> void main () {
>>>     int[] numbers = [1,2,3] ;
>>>
>>>     writefln("numbers before = ", numbers);
>>>     apply(numbers, TAddN!(40));
>>>     writefln("numbers after = ", numbers);
>>> }

Now that, actually, I consider possibly a bug.  But a least the workaround was simple enough (and small enough to be inlined).

-- Chris Nicholson-Sauls
January 12, 2007
[edited quotes to fix top-posting]

Bradley Smith wrote:
> Bradley Smith wrote:
>> Chris Nicholson-Sauls wrote:
>>> import std .stdio ;
>>>
>>> alias int delegate(int n) AddFunc;
>>>
>>> template TAddN (int N) {
>>>   const TAddN = (int i) { return i + N; } ;
>>> }
>>>
>>> void apply (int[] array, AddFunc func) {
>>>   foreach (inout i; array) {
>>>     i = func(i);
>>>   }
>>> }
>>>
>>> void main () {
>>>     int[] numbers = [1,2,3] ;
>>>
>>>     writefln("numbers before = ", numbers);
>>>     apply(numbers, TAddN!(40));
>>>     writefln("numbers after = ", numbers);
>>> }
>>
>> Using DMD 1.0, I get errors on the template.
>>
>> closureWithTemplate.d(19): delegate
>> closureWithTemplate.TAddN!(40).__dgliteral2 is a nested function and
>> cannot be accessed from main
>> closureWithTemplate.d(6): Error: non-constant expression __dgliteral2
>
> Nevermind. I figured it out. The following works.
>
> import std.stdio;
>
> alias int delegate(int n) AddFunc;
>
> template addN(int N) {
>   AddFunc addN() {
>     return delegate int (int i) { return i + N; };
>   }
> }
>
> void apply (int[] array, AddFunc func) {
>   foreach (inout i; array) {
>     i = func(i);
>   }
> }
>
> void main () {
>     int[] numbers = [1,2,3] ;
>     writefln("numbers before = ", numbers);
>     apply(numbers, addN!(40));
>     writefln("numbers after = ", numbers);
> }

This also works:
-----
// Delegates replaced by functions and TAddN changed to template
// template function instead of template function pointer variable
// (so no delegate or function literals are needed)

import std.stdio;

alias int function(int n) AddFunc;

int TAddN (int N) (int i) { return i + N; }

void apply (int[] array, AddFunc func) {
  foreach (inout i; array) {
    i = func(i);
  }
}

void main () {
    int[] numbers = [1,2,3] ;

    writefln("numbers before = ", numbers);
    apply(numbers, &TAddN!(40));
    writefln("numbers after = ", numbers);
}
-----

But I agree that the fact the below doesn't work seems to be a bug:

-----
// Delegates replaced by functions

import std.stdio;

alias int function(int n) AddFunc;

template TAddN (int N) {
  const TAddN = function (int i) { return i + N; } ;
}

void apply (int[] array, AddFunc func) {
  foreach (inout i; array) {
    i = func(i);
  }
}

void main () {
    int[] numbers = [1,2,3] ;

    writefln("numbers before = ", numbers);
    apply(numbers, TAddN!(40));
    writefln("numbers after = ", numbers);
}
-----
test.d(6): Error: non-constant expression __funcliteral2

I can understand why the delegate version wouldn't work though. I mean, what would the context pointer be?
But the function version should compile IMHO.
1 2
Next ›   Last »