Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
May 20, 2014 Question about @nogc | ||||
---|---|---|---|---|
| ||||
Did I understand correct that a function can only be @nogc if also all functions that it calls are @nogc too (and of course it doesn't use the GC itself)? If so, should this be possible: string foo() { // use GC to allocate some string } bar @nogc { mixin(foo()); } Because, bar() didn't really call foo() but instead foo() is evaluated during compile time and it's result is now part of the code, right? |
May 20, 2014 Re: Question about @nogc | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dominikus Dittes Scherkl | On Tuesday, 20 May 2014 at 12:25:11 UTC, Dominikus Dittes Scherkl wrote:
> Did I understand correct that a function can only be @nogc if also all functions that it calls are @nogc too (and of course it doesn't use the GC itself)?
>
> If so, should this be possible:
>
> string foo()
> {
> // use GC to allocate some string
> }
>
> bar @nogc
> {
> mixin(foo());
> }
>
> Because, bar() didn't really call foo() but instead foo() is evaluated during compile time and it's result is now part of the code, right?
Right.
It's the same mechanics you'd get from pure/nothrow and @safe+@trusted
|
May 20, 2014 Re: Question about @nogc | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dominikus Dittes Scherkl | On Tuesday, 20 May 2014 at 12:25:11 UTC, Dominikus Dittes Scherkl wrote:
> Did I understand correct that a function can only be @nogc if also all functions that it calls are @nogc too (and of course it doesn't use the GC itself)?
>
> If so, should this be possible:
>
> string foo()
> {
> // use GC to allocate some string
> }
>
> bar @nogc
> {
> mixin(foo());
> }
>
> Because, bar() didn't really call foo() but instead foo() is evaluated during compile time and it's result is now part of the code, right?
Yes, that should be allowed.
|
May 20, 2014 Re: Question about @nogc | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On Tuesday, 20 May 2014 at 17:14:31 UTC, John Colvin wrote:
> On Tuesday, 20 May 2014 at 12:25:11 UTC, Dominikus Dittes Scherkl wrote:
>> Did I understand correct that a function can only be @nogc if also all functions that it calls are @nogc too (and of course it doesn't use the GC itself)?
>>
>> If so, should this be possible:
>>
>> string foo()
>> {
>> // use GC to allocate some string
>> }
>>
>> bar @nogc
>> {
>> mixin(foo());
>> }
>>
>> Because, bar() didn't really call foo() but instead foo() is evaluated during compile time and it's result is now part of the code, right?
>
> Yes, that should be allowed.
Thanks. This is nice to know, because I will use this a lot in the future:
/// create a fixed size array with the given name and with *max* entries
/// of immutable values of the same type as the return value of the
/// given function.
/// it contains the values of that function in the range [0..max].
string makeLookupTable(alias fn, uint max=255)(string name) pure @safe if(is(typeof(fn(max))))
{
string table = "immutable " ~ to!string(typeof(fn(max))) ~ "[" ~ to!string(max+1) ~ "] " ~ name ~"= [ ";
foreach(i; 0..max) table ~= to!string(fn(i) ~ ", ";
return table ~ to!string(fn(max) ~" ]";
}
|
May 20, 2014 Re: Question about @nogc | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dominikus Dittes Scherkl | On Tuesday, 20 May 2014 at 20:15:09 UTC, Dominikus Dittes Scherkl wrote: > /// create a fixed size array with the given name and with *max* entries max + 1 entries > /// of immutable values of the same type as the return value of the > /// given function. > /// it contains the values of that function in the range [0..max]. > string makeLookupTable(alias fn, uint max=255)(string name) pure @safe if(is(typeof(fn(max)))) > { > string table = "immutable " ~ to!string(typeof(fn(max))) ~ "[" ~ to!string(max+1) ~ "] " ~ name ~"= [ "; > foreach(i; 0..max) table ~= to!string(fn(i) ~ ", "; > return table ~ to!string(fn(max) ~" ]"; > } Couldn't resist purging that of the string fiddling: private template staticIota(uint n) { import std.typetuple: TypeTuple; static if(n == 0) alias staticIota = TypeTuple!(); else alias staticIota = TypeTuple!(.staticIota!(n - 1), n - 1); } template lookupTable(alias fn, uint max = 255) { import std.traits: ReturnType; import std.typetuple: staticMap; static assert(max < uint.max); enum length = max + 1; enum ctfn(uint x) = fn(x); alias elements = staticMap!(ctfn, staticIota!length); enum ReturnType!fn[length] lookupTable = [elements]; } void main() { char f(uint x) pure @safe {return x == 42 ? '!' : '.';} static immutable t = lookupTable!f; static assert(is(typeof(t) == immutable char[256])); assert(t[42] == '!'); } |
May 20, 2014 Re: Question about @nogc | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Tuesday, 20 May 2014 at 21:04:37 UTC, anonymous wrote:
> On Tuesday, 20 May 2014 at 20:15:09 UTC, Dominikus Dittes Scherkl
> wrote:
>> /// create a fixed size array with the given name and with *max* entries
>
> max + 1 entries
>
>> /// of immutable values of the same type as the return value of the
>> /// given function.
>> /// it contains the values of that function in the range [0..max].
>> string makeLookupTable(alias fn, uint max=255)(string name) pure @safe if(is(typeof(fn(max))))
>> {
>> string table = "immutable " ~ to!string(typeof(fn(max))) ~ "[" ~ to!string(max+1) ~ "] " ~ name ~"= [ ";
>> foreach(i; 0..max) table ~= to!string(fn(i) ~ ", ";
>> return table ~ to!string(fn(max) ~" ]";
>> }
>
> Couldn't resist purging that of the string fiddling:
>
> ...
>
> enum ReturnType!fn[length] lookupTable = [elements];
Depending on what the usecase is, you might want to change that to static immutable instead:
static immutable ReturnType!fn[length] lookupTable = [elements];
Remember that when using an enum, the compiler will create a *new* variable on every use. While the compiler can sometimes avoid actually allocating, it may also insert some object code bloat to do so.
|
May 20, 2014 Re: Question about @nogc | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Tuesday, 20 May 2014 at 21:16:26 UTC, monarch_dodra wrote:
>> enum ReturnType!fn[length] lookupTable = [elements];
>
> Depending on what the usecase is, you might want to change that to static immutable instead:
>
> static immutable ReturnType!fn[length] lookupTable = [elements];
>
> Remember that when using an enum, the compiler will create a *new* variable on every use. While the compiler can sometimes avoid actually allocating, it may also insert some object code bloat to do so.
That's the "return" line of a template. In the usage example in
main() it's static immutable.
|
May 20, 2014 Re: Question about @nogc | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On 05/20/2014 11:04 PM, anonymous wrote: > On Tuesday, 20 May 2014 at 20:15:09 UTC, Dominikus Dittes Scherkl > wrote: >> /// create a fixed size array with the given name and with *max* entries > > max + 1 entries > >> /// of immutable values of the same type as the return value of the >> /// given function. >> /// it contains the values of that function in the range [0..max]. >> string makeLookupTable(alias fn, uint max=255)(string name) pure @safe >> if(is(typeof(fn(max)))) >> { >> string table = "immutable " ~ to!string(typeof(fn(max))) ~ "[" ~ >> to!string(max+1) ~ "] " ~ name ~"= [ "; >> foreach(i; 0..max) table ~= to!string(fn(i) ~ ", "; >> return table ~ to!string(fn(max) ~" ]"; >> } > > Couldn't resist purging that of the string fiddling: > > private template staticIota(uint n) > { > import std.typetuple: TypeTuple; > static if(n == 0) alias staticIota = TypeTuple!(); > else alias staticIota = TypeTuple!(.staticIota!(n - 1), n - > 1); > } > > template lookupTable(alias fn, uint max = 255) > { > import std.traits: ReturnType; > import std.typetuple: staticMap; > static assert(max < uint.max); > enum length = max + 1; > enum ctfn(uint x) = fn(x); > alias elements = staticMap!(ctfn, staticIota!length); > enum ReturnType!fn[length] lookupTable = [elements]; > } > ... Wtf. Is this really the point you are trying to make? :o) This achieves the same: template lookupTable(alias fn,uint max=255){ static assert(max<uint.max); enum ReturnType!fn[max+1] lookupTable=iota(0,max+1).map!fn.array; } > void main() > { > char f(uint x) pure @safe {return x == 42 ? '!' : '.';} > static immutable t = lookupTable!f; > static assert(is(typeof(t) == immutable char[256])); > assert(t[42] == '!'); > } |
May 20, 2014 Re: Question about @nogc | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On 05/20/2014 11:48 PM, Timon Gehr wrote:
>
> This achieves the same:
>
> template lookupTable(alias fn,uint max=255){
> static assert(max<uint.max);
> enum ReturnType!fn[max+1] lookupTable=iota(0,max+1).map!fn.array;
> }
(Though I'd never actually do template argument checking in a static assert within the template body.)
|
May 20, 2014 Re: Question about @nogc | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Tuesday, 20 May 2014 at 21:48:08 UTC, Timon Gehr wrote:
> Wtf. Is this really the point you are trying to make? :o)
>
> This achieves the same:
>
> template lookupTable(alias fn,uint max=255){
> static assert(max<uint.max);
> enum ReturnType!fn[max+1] lookupTable=iota(0,max+1).map!fn.array;
> }
Ha! That's ... much better. I wasn't trying to make any point,
though.
|
Copyright © 1999-2021 by the D Language Foundation