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:
- How do I print the contents of a Tuple using for loops? Or any other method?
- 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:
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