On 7/2/21 12:21 AM, Kirill wrote:
I have a `Tuple!(string, ..., string)[] data` that I would like to print out:
`a   b   c`
`1   2   3`
`4   5   6`

    Furthermore, I want to be able to print any N rows and M columns of that table. For instance:
         `b   c`
         `2   3`
         or
         `1   2   3`
         `4   5   6`

I am using for loops for that:

         // inside some function(rows, cols):
         immutable startFromRow = ...;
         immutable endWithRow = ...;
         immutable startFromCol = ...;
         immutable endWithCol = ...;

         // print data
         for(size_t i = startFromRow; i < endWithRow; i++) {
             for(size_t j = startFromCol; j < endWithCol; j++) {
                 writef("%s", data[i][j]);
             }
             writef("\n");
         }

And the compiler puts out the following:
`Error: variable 'j' cannot be read at compile time`

I tried `data[i].expand[j]`, but the same error occurs anyway.

I have two questions:
1. How do I print the contents of a Tuple using for loops? Or any other method?
2. What am I missing? How does it actually work under the hood?

So a tuple is really like an unnamed group of variables.

A `Tuple!(int, int, int)` is really like three ints that are all separate variables. It's just that they are named via the group. It is NOT like an array, it's more like a struct with fields that have indexes instead of names.

In order to print them in a loop, based on *runtime* data, you need to bridge the gap between runtime and compile time. Why? Because a Tuple does not necessarily contain the same types for every value, so `tup[0]` might have a different type than `tup[1]`. Because D is strongly-typed, you need to access these with *compile-time* indexes, so it knows what type you are using.

Imagine you have a struct, and you want to use a runtime string to access a given field. This is essentially the same, except it's an index and not a name.

A typical way to bridge the gap is to use a switch to validate the runtime variable, and then use the compile-time equivalalent to actually get the data.

For example, you could write a function like:

```d
void printItem(Tuple!(...) vals, size_t index)
{
theswitch:
    final switch(index)
    {
       static foreach(ctIdx; 0 .. vals.length) {
            case ctIdx: writeln(vals[ctIdx]);
            break theswitch;
       }
    }
}
```

Now, if you want to just print them in order, without any runtime details, you can just use foreach on a tuple and it works (the foreach variables are compile-time determined).

-Steve

Reply via email to