www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Filling an array at compile time

reply Vindex <tech.vindex gmail.com> writes:
Will the loop (foreach) run at compile time? How can I make it 
work at compile time?

```
import std.csv, std.stdio;

alias Record = Tuple!(string, string, string);

immutable string[][] table;

shared static this() {
     string csvText = import("file.csv");
     foreach (record; csvReader!Record(csvText)) {
         table ~= [record[0], record[1], record[2]];
     }
}

void main() {
     writeln(table):
}
```
Feb 09 2022
next sibling parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 9 February 2022 at 08:12:52 UTC, Vindex wrote:
 Will the loop (foreach) run at compile time? How can I make it 
 work at compile time?

 ```
 import std.csv, std.stdio;

 alias Record = Tuple!(string, string, string);

 immutable string[][] table;

 shared static this() {
     string csvText = import("file.csv");
     foreach (record; csvReader!Record(csvText)) {
         table ~= [record[0], record[1], record[2]];
     }
 }

 void main() {
     writeln(table):
 }
 ```
It will not run at compile-time because csvText is a runtime variable. It should be enum to be accessible at compile-time. The second issue is that your foreach should probably be static foreach. The third issue is how you're creating "table". The append operation will be executed at runtime, which means that even if the loop runs at compile-time then you're effectively not winning anything and it basically just becomes a loop-unroll manually done. The solution would be to create a function that returns a string that is equivalent to the contents of the array you want to create, as if you wrote the content yourself. And then simply using mixin to "set" the value of the table by calling that function. Ex. ``` string getInt() { return "immutable a = 10;"; } mixin(getInt); // The variable a is accessible here ... ```
Feb 09 2022
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 2/9/22 01:07, bauss wrote:

 It will not run at compile-time because csvText is a runtime variable.
 It should be enum to be accessible at compile-time.
Yes. For the sake of completeness, any expression needed at compile time will be (attempted to be) executed at compile time. For example, an expression used as a template parameter will be executed at compile time as well.
 The append operation
 will be executed at runtime, which means that even if the loop runs at
 compile-time then you're effectively not winning anything and it
 basically just becomes a loop-unroll manually done.
That's not true. It all depends on how the expression is needed. If for example, the variable were defined as enum, the compiler had to execute the code at compile time to compute its value.
 The solution would be to create a function that returns a string [...]
 And then simply using mixin
That is unnecessary and hurts readability. :/ Most programmers see string mixins as a last resort. In any case, some people may find a compile-time file parsing example that I included in a presentation: https://youtu.be/dRORNQIB2wA?t=3157 Ali
Feb 09 2022
next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 2/9/22 08:37, Ali Çehreli wrote:

 In any case, some people may find a compile-time file parsing example
 that I included in a presentation:
That should mean "may find interesting". And I've just realized that the chapter link is off in that video. This is the beginning of that section: https://www.youtube.com/watch?v=dRORNQIB2wA&t=3065s Ali
Feb 09 2022
prev sibling parent bauss <jj_1337 live.dk> writes:
On Wednesday, 9 February 2022 at 16:37:22 UTC, Ali Çehreli wrote:
 On 2/9/22 01:07, bauss wrote:

 It will not run at compile-time because csvText is a runtime
variable.
 It should be enum to be accessible at compile-time.
Yes. For the sake of completeness, any expression needed at compile time will be (attempted to be) executed at compile time. For example, an expression used as a template parameter will be executed at compile time as well.
 The append operation
 will be executed at runtime, which means that even if the
loop runs at
 compile-time then you're effectively not winning anything and
it
 basically just becomes a loop-unroll manually done.
That's not true. It all depends on how the expression is needed. If for example, the variable were defined as enum, the compiler had to execute the code at compile time to compute its value.
 The solution would be to create a function that returns a
string [...]
 And then simply using mixin
That is unnecessary and hurts readability. :/ Most programmers see string mixins as a last resort. In any case, some people may find a compile-time file parsing example that I included in a presentation: https://youtu.be/dRORNQIB2wA?t=3157 Ali
Thank you Ali for the clarifications
Feb 09 2022
prev sibling parent reply Anonymouse <zorael gmail.com> writes:
On Wednesday, 9 February 2022 at 08:12:52 UTC, Vindex wrote:
 Will the loop (foreach) run at compile time? How can I make it 
 work at compile time?

 ```
 import std.csv, std.stdio;

 alias Record = Tuple!(string, string, string);

 immutable string[][] table;

 shared static this() {
     string csvText = import("file.csv");
     foreach (record; csvReader!Record(csvText)) {
         table ~= [record[0], record[1], record[2]];
     }
 }

 void main() {
     writeln(table):
 }
 ```
I would do this. ``` import std; alias Record = Tuple!(string, string, string); static immutable string[][] table = () { string[][] table; string csvText = import("file.csv"); foreach (record; csvReader!Record(csvText)) { table ~= [record[0], record[1], record[2]]; } return table; }(); pragma(msg, table); // Available at compile-time void main() { writeln(table); } ``` And then `-J{path}` to tell the compiler where to find `file.csv`. ``` dmd -J. csv.d ```
Feb 09 2022
next sibling parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 9 February 2022 at 10:01:15 UTC, Anonymouse wrote:
 On Wednesday, 9 February 2022 at 08:12:52 UTC, Vindex wrote:
 Will the loop (foreach) run at compile time? How can I make it 
 work at compile time?

 ```
 import std.csv, std.stdio;

 alias Record = Tuple!(string, string, string);

 immutable string[][] table;

 shared static this() {
     string csvText = import("file.csv");
     foreach (record; csvReader!Record(csvText)) {
         table ~= [record[0], record[1], record[2]];
     }
 }

 void main() {
     writeln(table):
 }
 ```
I would do this. ``` import std; alias Record = Tuple!(string, string, string); static immutable string[][] table = () { string[][] table; string csvText = import("file.csv"); foreach (record; csvReader!Record(csvText)) { table ~= [record[0], record[1], record[2]]; } return table; }(); pragma(msg, table); // Available at compile-time void main() { writeln(table); } ``` And then `-J{path}` to tell the compiler where to find `file.csv`. ``` dmd -J. csv.d ```
Is it guaranteed that the value is initialized at compiletime however? Something being available at compiletime isn't the same as being initialized at compiletime only. If it's guaranteed then that's indeed the best solution.
Feb 09 2022
parent user1234 <user1234 12.de> writes:
On Wednesday, 9 February 2022 at 10:25:34 UTC, bauss wrote:
 Is it guaranteed that the value is initialized at compiletime 
 however?
yes, D guarentees this at 100%.
Feb 09 2022
prev sibling parent Vindex <tech.vindex gmail.com> writes:
On Wednesday, 9 February 2022 at 10:01:15 UTC, Anonymouse wrote:
 On Wednesday, 9 February 2022 at 08:12:52 UTC, Vindex wrote:
 [...]
I would do this. ``` import std; alias Record = Tuple!(string, string, string); static immutable string[][] table = () { string[][] table; string csvText = import("file.csv"); foreach (record; csvReader!Record(csvText)) { table ~= [record[0], record[1], record[2]]; } return table; }(); pragma(msg, table); // Available at compile-time void main() { writeln(table); } ``` And then `-J{path}` to tell the compiler where to find `file.csv`. ``` dmd -J. csv.d ```
Thanks! It does indeed work at compile time.
Feb 09 2022