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