Jump to page: 1 2
Thread overview
Compile-time global mutables
Jun 30, 2022
HuskyNator
Jun 30, 2022
bauss
Jun 30, 2022
HuskyNator
Jun 30, 2022
HuskyNator
Jun 30, 2022
Paul Backus
Jun 30, 2022
Adam Ruppe
Jun 30, 2022
bauss
Jun 30, 2022
HuskyNator
Jun 30, 2022
Adam Ruppe
Jun 30, 2022
HuskyNator
Jun 30, 2022
Adam D Ruppe
Jun 30, 2022
HuskyNator
Jun 30, 2022
Adam D Ruppe
Jul 01, 2022
HuskyNator
Jul 01, 2022
Adam D Ruppe
Jul 01, 2022
HuskyNator
Jul 01, 2022
HuskyNator
Jul 01, 2022
HuskyNator
Jun 30, 2022
Paul Backus
June 30, 2022

I've found several instances in which incrementation during compile time is required.
One example is generation of unique ID's (although there might be some workarounds), another interesting idea the registration of a function's call-count to some image loader;

>

Anyone know of a way in c++ to track static resource usage at compile time, basically i am trying to find a way so an routine can just do Image("foobar.jpeg2000"), at an arbitrary point in operation and I'll make sure the resources are resident before the Job gets run.

Although this references c++, I have attempted to make this work in D. It seems there are no workarounds that would make this work sadly. (I've even tried writing to files instead but this is not possible during ctfe)

Essentially speaking, there are numerous instances in which generating a list or incrementing a value is useful during compile-time. I find this should be possible.

One main argument against this seems to be the non-deterministic nature of this, though this is not an issue in virtually all cases in which doing this is useful or necessary I find. Essentially speaking when order does not matter and membership is only required during run-time.

Are there other limiting factors preventing this possibility? It would allow for some powerful things that currently seem impossible to implement (save for some case-specific workarounds).

June 30, 2022

On Thursday, 30 June 2022 at 12:26:54 UTC, HuskyNator wrote:

>

I've found several instances in which incrementation during compile time is required.
One example is generation of unique ID's (although there might be some workarounds), another interesting idea the registration of a function's call-count to some image loader;

>

Anyone know of a way in c++ to track static resource usage at compile time, basically i am trying to find a way so an routine can just do Image("foobar.jpeg2000"), at an arbitrary point in operation and I'll make sure the resources are resident before the Job gets run.

Although this references c++, I have attempted to make this work in D. It seems there are no workarounds that would make this work sadly. (I've even tried writing to files instead but this is not possible during ctfe)

Essentially speaking, there are numerous instances in which generating a list or incrementing a value is useful during compile-time. I find this should be possible.

One main argument against this seems to be the non-deterministic nature of this, though this is not an issue in virtually all cases in which doing this is useful or necessary I find. Essentially speaking when order does not matter and membership is only required during run-time.

Are there other limiting factors preventing this possibility? It would allow for some powerful things that currently seem impossible to implement (save for some case-specific workarounds).

You can already do that.

enum counter(size_t x = [__traits(allMembers, mixin(__MODULE__))].length)=x;
char[] member(ulong x)
{
    char[] buf = "void[0] _X0000000000000000;".dup;
    enum mapping = "0123456789abcdef";
    foreach_reverse(i; buf.length-17 .. buf.length-1)
    {
        buf[i] = mapping[x & 0xf];
        x >>= 4;
    }
    return buf;
}
mixin template increment()
{
    mixin(member(counter!()));
}

pragma(msg, counter!());
mixin increment;
pragma(msg, counter!());
mixin increment;
pragma(msg, counter!());

Credits: p0nce

June 30, 2022

On Thursday, 30 June 2022 at 12:26:54 UTC, HuskyNator wrote:

>

One example is generation of unique ID's (although there might be some workarounds)

Here's a mixin that works for this particular use-case:

enum gensym = q{"_gensym" ~ __traits(identifier, {})["__lambda".length .. $]};

// Works multiple times on the same line
pragma(msg, mixin(gensym)); pragma(msg, mixin(gensym));
June 30, 2022

On Thursday, 30 June 2022 at 12:55:43 UTC, bauss wrote:

>

You can already do that.

enum counter(size_t x = [__traits(allMembers, mixin(__MODULE__))].length)=x;
char[] member(ulong x)
{
    char[] buf = "void[0] _X0000000000000000;".dup;
    enum mapping = "0123456789abcdef";
    foreach_reverse(i; buf.length-17 .. buf.length-1)
    {
        buf[i] = mapping[x & 0xf];
        x >>= 4;
    }
    return buf;
}
mixin template increment()
{
    mixin(member(counter!()));
}

pragma(msg, counter!());
mixin increment;
pragma(msg, counter!());
mixin increment;
pragma(msg, counter!());

Credits: p0nce

I'm assuming this works for counters in general? (although I do not see how the member function works, this seems like a very sophisticated / fault-sensitive workaround)
Do you know there's workarounds for the other case(s) I have described?

June 30, 2022

On Thursday, 30 June 2022 at 13:04:39 UTC, HuskyNator wrote:

>

I'm assuming this works for counters in general? (although I do not see how the member function works, this seems like a very sophisticated / fault-sensitive workaround)
Do you know there's workarounds for the other case(s) I have described?

Sidenote, would this require separate files for every counter one requires? Seeing as allMembers is used. (assuming I understand the code correctly)

June 30, 2022

On Thursday, 30 June 2022 at 12:26:54 UTC, HuskyNator wrote:

>

Essentially speaking, there are numerous instances in which generating a list or incrementing a value is useful during compile-time. I find this should be possible.

What are those instances?

The file example you showed is done with a perfectly normal constructor, it loads the file before moving on.

If you want to collect a bunch of things and load them at once, you can use a module constructor; a static this in a template and the compiler adds them all together.

Those module constructors can also increment normal runtime variables.

I've done a lot of things in D and managed to get by never using a compile time counter...

June 30, 2022

On Thursday, 30 June 2022 at 13:16:48 UTC, Adam Ruppe wrote:

>

On Thursday, 30 June 2022 at 12:26:54 UTC, HuskyNator wrote:

>

Essentially speaking, there are numerous instances in which generating a list or incrementing a value is useful during compile-time. I find this should be possible.

What are those instances?

The file example you showed is done with a perfectly normal constructor, it loads the file before moving on.

If you want to collect a bunch of things and load them at once, you can use a module constructor; a static this in a template and the compiler adds them all together.

Those module constructors can also increment normal runtime variables.

I've done a lot of things in D and managed to get by never using a compile time counter...

Yeah, me too. The only time I have ever needed it was for demonstrating concepts that were specific to the language and not for any productive work.

June 30, 2022

On Thursday, 30 June 2022 at 13:16:48 UTC, Adam Ruppe wrote:

>

If you want to collect a bunch of things and load them at once, you can use a module constructor; a static this in a template and the compiler adds them all together.

Not sure I see how that would apply to this example.
How would you write a static constructor that loads in all files used somewhere in the source code? This seems like a prerequisite to being able to do that.

June 30, 2022

On Thursday, 30 June 2022 at 13:39:57 UTC, HuskyNator wrote:

>

How would you write a static constructor that loads in all files used somewhere in the source code? This seems like a prerequisite to being able to do that.

template file(string name) {
import yourproject.allfiles;

shared static this() {
    allfiles ~= name;
}

enum file = name;

}

Use it like:

auto img = Image(file!"thing.jpg");

And then yourproject.allfiles module has:

__gshared string[] allfiles; // you MUST only write to it from those constructors but afterwards can iterate it since you know it is immutable from that point on

And somewhere in your main() function:

void main() {
import yourpoject.allfiles;
foreach(file; allfiles)
loadFile(file);
}

Or similar. The key point is the magic file template builds an array of all files in its static constructors which you then process later at runtime.

June 30, 2022

On Thursday, 30 June 2022 at 13:39:57 UTC, HuskyNator wrote:

>

On Thursday, 30 June 2022 at 13:16:48 UTC, Adam Ruppe wrote:

>

If you want to collect a bunch of things and load them at once, you can use a module constructor; a static this in a template and the compiler adds them all together.

Not sure I see how that would apply to this example.
How would you write a static constructor that loads in all files used somewhere in the source code? This seems like a prerequisite to being able to do that.

string[] files;

template register(string file)
{
    static this()
    {
        // TODO: actually load the file
        files ~= file;
    }
    void register() {}
}

void foo()
{
    register!"foo";
}

void bar()
{
    register!"bar";
}

void main()
{
    import std.stdio;
    writeln(files); // ["foo", "bar"]
}
« First   ‹ Prev
1 2