August 16, 2015 Re: How to provide this arg or functor for algorithm? | ||||
---|---|---|---|---|
| ||||
Posted in reply to cym13 | On 08/16/2015 03:36 PM, cym13 wrote:
> On Sunday, 16 August 2015 at 22:22:07 UTC, Ali Çehreli wrote:
>>
>> // HERE:
>> // Error: function deneme.func @nogc function allocates
>> // a closure with the GC
>> @nogc auto func(uint[] arr, DelegateRef d)
>> {
>> return arr.map!(a => d.d(a));
>> }
>
> Aren't you making another delegate in the map by using "=>" that needs
> to allocate because it uses 'd' which is out of its scope?
I did not see that at all. :) I've finally gotten it to work by stepping into template realm where the compiler is a master of attributes: :)
import std.stdio;
import std.range;
import std.algorithm;
struct Caller
{
this(uint context) {
_context = context;
}
// ADDED pure
pure uint method(uint value) {
return _context * value;
}
uint _context;
}
// Now the type of d is a template parameter
@nogc auto func(Func)(uint[] arr, Func d)
{
return arr.map!(d);
}
void main(string[] args)
{
uint[] arr = [1,2,3];
uint context = 2;
auto c = Caller(context);
auto d = &c.method;
writeln(func(arr, d));
}
Prints:
[2, 4, 6]
Ali
|
August 17, 2015 Re: How to provide this arg or functor for algorithm? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Sunday, 16 August 2015 at 23:05:42 UTC, Ali Çehreli wrote:
> // Now the type of d is a template parameter
> @nogc auto func(Func)(uint[] arr, Func d)
> {
> return arr.map!(d);
> }
Huh. I think func being a template is the key here. When the original code is put in a template, it works too (with 2.068):
----
void func()() @nogc
{
import std.algorithm;
uint[3] arr = [1,2,3];
uint context = 2;
auto r = arr[].map!(delegate(value) { return value * context; });
}
void main()
{
func();
}
----
|
August 17, 2015 Re: How to provide this arg or functor for algorithm? | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Monday, 17 August 2015 at 09:51:47 UTC, anonymous wrote:
> Huh. I think func being a template is the key here. When the original code is put in a template, it works too (with 2.068):
Nope, it "works" only because "r" is unreferenced and gets thrown out. Just try using r.front there, for example, and the error returns.
|
August 17, 2015 Re: How to provide this arg or functor for algorithm? | ||||
---|---|---|---|---|
| ||||
Posted in reply to thedeemon | On Monday, 17 August 2015 at 10:28:33 UTC, thedeemon wrote:
> Nope, it "works" only because "r" is unreferenced and gets thrown out. Just try using r.front there, for example, and the error returns.
You're right, it falls short.
But I think r not being referenced is not exactly it. Using front in Ali's func breaks it in the same way. And returning r from func works.
Wait, returning r from func works? Yes:
----
auto func()(uint[] arr, uint context) @nogc
{
import std.algorithm;
auto r = arr[].map!(delegate(value) { return value * context; });
return r;
}
void main() @nogc
{
uint[3] arr = [1,2,3];
uint context = 2;
auto r = func(arr[], context);
import std.algorithm: equal;
import std.range: only;
assert(equal(r, only(2, 4, 6)));
}
----
Is that supposed to compile? A closure is needed for the delegate, isn't it? With @nogc, where is the closure stored? This looks like an accepts-invalid bug to me.
It doesn't compile when func is not a template. So maybe the check is broken for templates.
It also doesn't compile with 2.067, so this may be a regression.
Coming back to Ali's code, here's a version that shows that func doesn't need template parameters, but it needs to be a template:
----
import std.stdio;
import std.algorithm;
struct Caller
{
uint method(uint value) pure @nogc {
return _context * value;
}
uint _context;
}
auto func()(uint[] arr, uint delegate(uint) pure @nogc d) @nogc
{
return arr.map!(d);
}
void main() @nogc
{
uint[3] arr = [1,2,3];
uint context = 2;
auto c = Caller(context);
auto d = &c.method;
auto r = func(arr[], d);
import std.algorithm: equal;
import std.range: only;
assert(equal(r, only(2, 4, 6)));
}
----
I think this relies on the same discrepancy as the problematic code above.
|
August 17, 2015 Re: How to provide this arg or functor for algorithm? | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Monday, 17 August 2015 at 12:38:05 UTC, anonymous wrote:
> auto func()(uint[] arr, uint delegate(uint) pure @nogc d) @nogc
> {
> return arr.map!(d);
> }
>
> void main() @nogc
> {
> uint[3] arr = [1,2,3];
> uint context = 2;
> auto c = Caller(context);
> auto d = &c.method;
>
> auto r = func(arr[], d);
>
> import std.algorithm: equal;
> import std.range: only;
> assert(equal(r, only(2, 4, 6)));
> }
I've just checked with my runtime GC hook. Here the call to func() allocates 12 bytes via gc_malloc, and it's the same for a 4-elements array, so it's not for the array itself, it's for a closure, I think.
|
August 17, 2015 Re: How to provide this arg or functor for algorithm? | ||||
---|---|---|---|---|
| ||||
Posted in reply to thedeemon | On Monday, 17 August 2015 at 16:18:50 UTC, thedeemon wrote:
> I've just checked with my runtime GC hook. Here the call to func() allocates 12 bytes via gc_malloc, and it's the same for a 4-elements array, so it's not for the array itself, it's for a closure, I think.
Also, compiling with -vgc says nothing, compiler (2.068) seems to miss this allocation.
|
August 17, 2015 Re: How to provide this arg or functor for algorithm? | ||||
---|---|---|---|---|
| ||||
Posted in reply to thedeemon | On Monday, 17 August 2015 at 16:21:16 UTC, thedeemon wrote: > On Monday, 17 August 2015 at 16:18:50 UTC, thedeemon wrote: >> I've just checked with my runtime GC hook. Here the call to func() allocates 12 bytes via gc_malloc, and it's the same for a 4-elements array, so it's not for the array itself, it's for a closure, I think. > > Also, compiling with -vgc says nothing, compiler (2.068) seems to miss this allocation. Thanks for confirming. It seems to be a known issue that the compiler doesn't recognize the @nogc violation by the closure: https://issues.dlang.org/show_bug.cgi?id=14771 That's not a regression, though. 2.067 rejecting the code has something to do with this assert: https://github.com/D-Programming-Language/phobos/blob/v2.067.1/std/algorithm/iteration.d#L453 (code is the same for 2.068). I don't know if that assert should trigger a @nogc violation or not. But anyway, the real issue is 14771, as far as I can tell. |
Copyright © 1999-2021 by the D Language Foundation