www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Bug or am I getting things wrong

reply Q. Schroll <qs.il.paperinik gmail.com> writes:
In the listing below the commented line should do exactly the 
same thing as the one above.

/// DimArr!(i, T) ==> T[][]...[] i times.
template DimArr(size_t i, T)
{
     static if (i == 0)  alias DimArr = T;
     else                alias DimArr = DimArr!(i - 1, T)[];
}


struct Array(T, size_t rk)
     if (rk > 1)
{
     private size_t[rk] dims;
     /+ ... +/
     auto toNestedArray() const
     {
         import std.range : iota;
         import std.format : format;
         enum dimsIndexed = `%(dims[%d]%|, 
%)`.format(dims.length.iota);
         auto result = mixin(`new DimArr!(rk, T)(` ~ dimsIndexed ~ 
`)`);
      // auto result = new DimArr!(rk, T)(mixin(dimsIndexed)));
         /+ ... +/
         return result;
     }
}

The one above does exactly what I want, but the lower one only 
uses the last dimension for some reason. I found out by using 
these pragmas

     pragma(msg, "'", dimsIndexed, "'");
     pragma(msg, ( new DimArr!(rk, T) ( mixin(dimsIndexed) ) 
).stringof);

Can someone please tell me what I'm getting wrong here, or is 
this a bug?
Jan 06 2016
next sibling parent John Colvin <john.loughran.colvin gmail.com> writes:
On Thursday, 7 January 2016 at 07:51:05 UTC, Q. Schroll wrote:
 In the listing below the commented line should do exactly the 
 same thing as the one above.

 /// DimArr!(i, T) ==> T[][]...[] i times.
 template DimArr(size_t i, T)
 {
     static if (i == 0)  alias DimArr = T;
     else                alias DimArr = DimArr!(i - 1, T)[];
 }


 struct Array(T, size_t rk)
     if (rk > 1)
 {
     private size_t[rk] dims;
     /+ ... +/
     auto toNestedArray() const
     {
         import std.range : iota;
         import std.format : format;
         enum dimsIndexed = `%(dims[%d]%|, 
 %)`.format(dims.length.iota);
         auto result = mixin(`new DimArr!(rk, T)(` ~ dimsIndexed 
 ~ `)`);
      // auto result = new DimArr!(rk, T)(mixin(dimsIndexed)));
         /+ ... +/
         return result;
     }
 }

 The one above does exactly what I want, but the lower one only 
 uses the last dimension for some reason. I found out by using 
 these pragmas

     pragma(msg, "'", dimsIndexed, "'");
     pragma(msg, ( new DimArr!(rk, T) ( mixin(dimsIndexed) ) 
 ).stringof);

 Can someone please tell me what I'm getting wrong here, or is 
 this a bug?
Wow, that's a new reason to hate the comma operator even more than I did before! The expression that you are mixing in is actually a sequence of sub-expressions seperated by the comma operator, which means each expression is evaluated and the last one is returned. Remember, mixins are not textual substitution like C macros. Normally speaking you get error messages if you forget that, and that's ok, but here the evil comma operator made a mess of things. Here's one way to achieve what you want: /// DimArr!(i, T) ==> T[][]...[] i times. template DimArr(size_t i, T) { static if (i == 0) alias DimArr = T; else alias DimArr = DimArr!(i - 1, T)[]; } template Repeat(T, size_t N) { import std.meta : AliasSeq; static if (N == 0) alias Repeat = AliasSeq!(); else alias Repeat = AliasSeq!(T, Repeat!(T, N-1)); } auto toTuple(T, size_t N)(T[N] arr) { import std.typecons : Tuple; import std.traits : Unqual; Tuple!(Repeat!(Unqual!T, N)) tup; foreach(i, _; tup) tup[i] = arr[i]; return tup; } struct Array(T, size_t rk) if (rk > 1) { private size_t[rk] dims; /+ ... +/ auto toNestedArray() const { auto result = new DimArr!(rk, T)(dims.toTuple.expand); /+ ... +/ return result; } }
Jan 07 2016
prev sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 01/06/2016 11:51 PM, Q. Schroll wrote:
 In the listing below the commented line should do exactly the same thing
 as the one above.

 /// DimArr!(i, T) ==> T[][]...[] i times.
 template DimArr(size_t i, T)
 {
      static if (i == 0)  alias DimArr = T;
      else                alias DimArr = DimArr!(i - 1, T)[];
 }


 struct Array(T, size_t rk)
      if (rk > 1)
 {
      private size_t[rk] dims;
      /+ ... +/
      auto toNestedArray() const
      {
          import std.range : iota;
          import std.format : format;
          enum dimsIndexed = `%(dims[%d]%|, %)`.format(dims.length.iota);
          auto result = mixin(`new DimArr!(rk, T)(` ~ dimsIndexed ~ `)`);
       // auto result = new DimArr!(rk, T)(mixin(dimsIndexed)));
          /+ ... +/
          return result;
      }
 }

 The one above does exactly what I want, but the lower one only uses the
 last dimension for some reason. I found out by using these pragmas

      pragma(msg, "'", dimsIndexed, "'");
      pragma(msg, ( new DimArr!(rk, T) ( mixin(dimsIndexed) ) ).stringof);

 Can someone please tell me what I'm getting wrong here, or is this a bug?
I don't see any difference with dmd v2.069.2. Both lines print the following: 'dims[0], dims[1], dims[2], dims[3], dims[4], dims[5], dims[6], dims[7], dims[8], dims[9]' new int[][][][][][][][][][](this.dims[9]) Here is the program: /// DimArr!(i, T) ==> T[][]...[] i times. template DimArr(size_t i, T) { static if (i == 0) alias DimArr = T; else alias DimArr = DimArr!(i - 1, T)[]; } struct Array(T, size_t rk) if (rk > 1) { private size_t[rk] dims; /+ ... +/ auto toNestedArray() const { import std.range : iota; import std.format : format; enum dimsIndexed = `%(dims[%d]%|, %)`.format(dims.length.iota); auto result = mixin(`new DimArr!(rk, T)(` ~ dimsIndexed ~ `)`); // auto result = new DimArr!(rk, T)(mixin(dimsIndexed)); /+ ... +/ pragma(msg, "'", dimsIndexed, "'"); pragma(msg, ( new DimArr!(rk, T) ( mixin(dimsIndexed) ) ).stringof); return result; } } void main() { auto a = Array!(int, 10)(); import std.stdio; writeln(a.toNestedArray()); } Ali
Jan 07 2016