Thread overview
dynamic get from variantArray() data table
Oct 13, 2015
data pulverizer
Oct 13, 2015
Alex Parrill
Oct 13, 2015
data pulverizer
Oct 13, 2015
Alex Parrill
October 13, 2015
Hi,

I am trying to use variantArray() as a data table object to hold columns each of which is an array of a specific type. I need to be able to get values from data table but I am having problems ...


import std.stdio; // i/o
import std.variant; // type variations

void main(){
  // Columns of the table
  string[] names = ["walter", "paul", "jeff", "andrie"];
  int[] age = [55, 62, 27, 52];
  string[] language = ["D", "Haskell", "Julia", "D"];
  Variant[] dt = variantArray(names, age, language);

  foreach(col; dt){
    foreach(el; col){
      // here I try a kind of dynamic cast operator
      auto x = el.get!(type(el)); // gives error
      write(x);
    }
    write("\n");
  }
}

data_table.d(37): Error: cannot infer type for el
data_table.d(38): Error: undefined identifier 'el'

Help

DP

October 13, 2015
On Tuesday, 13 October 2015 at 15:17:15 UTC, data pulverizer wrote:
> Hi,
>
> I am trying to use variantArray() as a data table object to hold columns each of which is an array of a specific type. I need to be able to get values from data table but I am having problems ...
>
>
> import std.stdio; // i/o
> import std.variant; // type variations
>
> void main(){
>   // Columns of the table
>   string[] names = ["walter", "paul", "jeff", "andrie"];
>   int[] age = [55, 62, 27, 52];
>   string[] language = ["D", "Haskell", "Julia", "D"];
>   Variant[] dt = variantArray(names, age, language);
>
>   foreach(col; dt){
>     foreach(el; col){
>       // here I try a kind of dynamic cast operator
>       auto x = el.get!(type(el)); // gives error
>       write(x);
>     }
>     write("\n");
>   }
> }
>
> data_table.d(37): Error: cannot infer type for el
> data_table.d(38): Error: undefined identifier 'el'
>
> Help
>
> DP

You're trying to iterate over a `Variant`, which isn't implemented.

You don't want to use a variant here anyway; you should use a struct or tuple for each entry in the table.



import std.typecons;

alias Entry = Tuple!(string, int, string);

void main() {
    auto table = [Entry("walter", 55, "D"), Entry("paul", 62, "Haskell"), ... ]; // complete array
    foreach(entry; table) {
        writeln(entry.expand);
    }
}

October 13, 2015
Thanks for the suggestion Alex, however I need the dynamic behaviour properties of variantArray(), writing a struct each time would be undesirable.

Perhaps I could boil down the question to something like, is there a way of writing

auto x = dt[0][0];
auto y = x.get!(x.type - or whatever); // to get the actual value of x rather than .VariantN! ... type

For some kind of auto cast back to basic type.

On Tuesday, 13 October 2015 at 15:51:40 UTC, Alex Parrill wrote:
> On Tuesday, 13 October 2015 at 15:17:15 UTC, data pulverizer wrote:
>> Hi,
>>
>> I am trying to use variantArray() as a data table object to hold columns each of which is an array of a specific type. I need to be able to get values from data table but I am having problems ...
>>
>>
>> import std.stdio; // i/o
>> import std.variant; // type variations
>>
>> void main(){
>>   // Columns of the table
>>   string[] names = ["walter", "paul", "jeff", "andrie"];
>>   int[] age = [55, 62, 27, 52];
>>   string[] language = ["D", "Haskell", "Julia", "D"];
>>   Variant[] dt = variantArray(names, age, language);
>>
>>   foreach(col; dt){
>>     foreach(el; col){
>>       // here I try a kind of dynamic cast operator
>>       auto x = el.get!(type(el)); // gives error
>>       write(x);
>>     }
>>     write("\n");
>>   }
>> }
>>
>> data_table.d(37): Error: cannot infer type for el
>> data_table.d(38): Error: undefined identifier 'el'
>>
>> Help
>>
>> DP
>
> You're trying to iterate over a `Variant`, which isn't implemented.
>
> You don't want to use a variant here anyway; you should use a struct or tuple for each entry in the table.
>
>
>
> import std.typecons;
>
> alias Entry = Tuple!(string, int, string);
>
> void main() {
>     auto table = [Entry("walter", 55, "D"), Entry("paul", 62, "Haskell"), ... ]; // complete array
>     foreach(entry; table) {
>         writeln(entry.expand);
>     }
> }


October 13, 2015
On Tuesday, 13 October 2015 at 16:22:36 UTC, data pulverizer wrote:
> Thanks for the suggestion Alex, however I need the dynamic behaviour properties of variantArray(), writing a struct each time would be undesirable.
>
> Perhaps I could boil down the question to something like, is there a way of writing
>
> auto x = dt[0][0];
> auto y = x.get!(x.type - or whatever); // to get the actual value of x rather than .VariantN! ... type
>
> For some kind of auto cast back to basic type.

The problem is that you can't do `x.get!(x.type)`, because the type of the expression must be known at compile time, but `x.type` is a runtime value. You'd have to create a branch for each type that `x.type` might be.

But again, unless you are dealing with a truly dynamic layout (and not a bunch of fixed layouts), there's better options. For example, you can use `std.range.zip` to iterate through each column array in lockstep, returning tuples for each element.


foreach(entry; zip(names, ages, languages)) {
    write(entry.expand);
}