www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Printing Tuple!(...)[] using for loop?

reply Kirill <kirill.saidov mail.com> writes:
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?

Thanks in advance. Any help is greatly appreciated.
Jul 01
next sibling parent Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
On Friday, 2 July 2021 at 04:21:24 UTC, Kirill wrote:
 ...
1. use static foreach for tuple loop. 2. start column and end column should be known at compile time. Either make them immutable, or as enum constant, or pass them as an template argument. Tuple is basically a wrapper over built in tuple support from D. Check it's insides to se how it is done. So to index a field in a tuple you need to know which field you want to access at compile time since, each field in a tuple has different size, and cannot be indexed at runtime easily. Best regards, Alexandru.
Jul 02
prev sibling next sibling parent Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Friday, 2 July 2021 at 04:21:24 UTC, Kirill wrote:
 I have a `Tuple!(string, ..., string)[] data`
If there are only strings in the tuple, it could be simplified by making it a static array of strings instead. The compile-time index issue would go away. —Bastiaan
Jul 02
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
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
Jul 02