Thread overview
Question about @nogc
May 20, 2014
monarch_dodra
May 20, 2014
John Colvin
May 20, 2014
anonymous
May 20, 2014
monarch_dodra
May 20, 2014
anonymous
May 20, 2014
Timon Gehr
May 20, 2014
Timon Gehr
May 20, 2014
anonymous
May 20, 2014
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
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
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
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
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
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
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
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
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
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.