www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Error on recursive alias

reply Johan Mollevik <lijat.REMOVE.me gmail.com> writes:
I have some code from a couple of years ago that I'm trying to update 
to modern D.

I was first using the gdc compiler in debian stable which seems based 
on DMD 2.055 but that caused somthing that looks like memmory 
coruption.

Using the newer gdc compiler in debian sid (based on DMD 2.062 i think) 
I run into this error instead.

util.d:23: Error: alias util.foreachType!(uint[4LU][4LU]).foreachType 
recursive alias declaration

This is for code that have worked previously looking like this

template foreachType(T)
{
        static if(is(opApplyType!(T) V))
        {    
                static if(is(opApplyType!(V[$-1])))
                        alias Tuple!(V[0..$-1],foreachType!(V[$-1])) 
foreachType;
                else 
                        alias V foreachType;
        }    
        else 
        {    
                pragma(msg,"Failed to resolve type ");
                static assert(0,opApplyType!(T));
        }    
}

I can post all the source code if anyone is interested

What my ultimate goal is is to resurect my opApplyN function allowing 
me to do things like this

uint[4][4] block;
foreach(x,y,v;opApplyN(block))
	printf("%d %d %d\n",x,y,v);


If anyone know a more convinient way to achive that that would be 
helpfull as well.
Aug 25 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Johan Mollevik:

 What my ultimate goal is is to resurect my opApplyN function 
 allowing
 me to do things like this

 uint[4][4] block;
 foreach(x,y,v;opApplyN(block))
 	printf("%d %d %d\n",x,y,v);
What are x y and v? Bye, bearophile
Aug 25 2013
parent reply Johan Mollevik <lijat.REMOVE.me gmail.com> writes:
bearophile wrote:

 Johan Mollevik:
 
 What my ultimate goal is is to resurect my opApplyN function
 allowing
 me to do things like this

 uint[4][4] block;
 foreach(x,y,v;opApplyN(block))
 printf("%d %d %d\n",x,y,v);
What are x y and v? Bye, bearophile
x and y are the two dimensional indices into the 4x4 array block and v is the vallue at block[y][x]
Aug 25 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Johan Mollevik:

 x and y are the two dimensional indices into the 4x4 array 
 block and v
 is the vallue at block[y][x]
OK. Something like this? import std.stdio, std.typecons; struct NaturalScan(T) { T[][] data; size_t r, c; property bool empty() const pure nothrow { return r == data.length; } property Tuple!(size_t, size_t, T) front() const pure nothrow { return typeof(return)(r, c, data[r][c]); } void popFront() pure nothrow { c = (c + 1) % data[r].length; if (c == 0) r++; } } NaturalScan!T naturalScan(T)(T[][] m) { return typeof(return)(m); } void main() { auto mat = [[10, 20], [30, 40, 50], [60, 70]]; foreach (r, c, v; mat.naturalScan) writefln("%d %d %d", r, c, v); } Bye, bearophile
Aug 25 2013
parent reply Johan Mollevik <lijat.REMOVE.me gmail.com> writes:
bearophile wrote:

 Johan Mollevik:
 
 x and y are the two dimensional indices into the 4x4 array
 block and v
 is the vallue at block[y][x]
OK. Something like this? import std.stdio, std.typecons; struct NaturalScan(T) { T[][] data; size_t r, c; property bool empty() const pure nothrow { return r == data.length; } property Tuple!(size_t, size_t, T) front() const pure nothrow { return typeof(return)(r, c, data[r][c]); } void popFront() pure nothrow { c = (c + 1) % data[r].length; if (c == 0) r++; } } NaturalScan!T naturalScan(T)(T[][] m) { return typeof(return)(m); } void main() { auto mat = [[10, 20], [30, 40, 50], [60, 70]]; foreach (r, c, v; mat.naturalScan) writefln("%d %d %d", r, c, v); } Bye, bearophile
That looks like it might work for 2 dimensions and as that is the use case I have right now I might settle for that. (and I can add more overloads manually if needed) The original code was genereal enough to handle any number of dimensions thou. Bassically this would work like this uint[][][] array=... foreach(x,v;opApplyN(array)){//using only one index (x) //v has type uint[][] } foreach(x,y,v;opApplyN(array)){//using two indeces (x,y) //v has type uint[] } foreach(x,y,z,v;opApplyN(array)){//using three index (x,y,z) //v has type uint } So if someone know anything of why I get the error on recursive aliases I might try to get that working again otherwise I might try your code as it is enough for now Thnks for the help by the way
Aug 25 2013
parent reply Johan Mollevik <lijat.REMOVE.me gmail.com> writes:
Johan Mollevik wrote:

 bearophile wrote:
 
 Johan Mollevik:
 
 x and y are the two dimensional indices into the 4x4 array
 block and v
 is the vallue at block[y][x]
OK. Something like this? import std.stdio, std.typecons; struct NaturalScan(T) { T[][] data; size_t r, c; property bool empty() const pure nothrow { return r == data.length; } property Tuple!(size_t, size_t, T) front() const pure nothrow { return typeof(return)(r, c, data[r][c]); } void popFront() pure nothrow { c = (c + 1) % data[r].length; if (c == 0) r++; } } NaturalScan!T naturalScan(T)(T[][] m) { return typeof(return)(m); } void main() { auto mat = [[10, 20], [30, 40, 50], [60, 70]]; foreach (r, c, v; mat.naturalScan) writefln("%d %d %d", r, c, v); } Bye, bearophile
That looks like it might work for 2 dimensions and as that is the use case I have right now I might settle for that. (and I can add more overloads manually if needed) The original code was genereal enough to handle any number of dimensions thou. Bassically this would work like this uint[][][] array=... foreach(x,v;opApplyN(array)){//using only one index (x) //v has type uint[][] } foreach(x,y,v;opApplyN(array)){//using two indeces (x,y) //v has type uint[] } foreach(x,y,z,v;opApplyN(array)){//using three index (x,y,z) //v has type uint } So if someone know anything of why I get the error on recursive
aliases
 I might try to get that working again otherwise I might try your code
 as it is enough for now
 
 Thnks for the help by the way
Hmm, your solution does not work with static arrays it seems, will se if I can sort that out
Aug 25 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 08/25/2013 09:23 AM, Johan Mollevik wrote:

 Hmm, your solution does not work with static arrays it seems, will se
 if I can sort that out
Probably due to the fact that static arrays cannot be InputRanges because they cannot lose elements by popFront(). A slice to the entire array is an InputRange though: foreach (e; myStaticArray) // compilation error foreach (e; myStaticArray[]) // works Ali
Aug 25 2013
parent Johan Mollevik <lijat.REMOVE.me gmail.com> writes:
Ali Çehreli wrote:

 On 08/25/2013 09:23 AM, Johan Mollevik wrote:
 
  > Hmm, your solution does not work with static arrays it seems, will 
se
  > if I can sort that out
 
 Probably due to the fact that static arrays cannot be InputRanges
 because they cannot lose elements by popFront(). A slice to the 
entire
 array is an InputRange though:
 
      foreach (e; myStaticArray)      // compilation error
 
      foreach (e; myStaticArray[])    // works
 
 Ali
I accutally got my original code to work just now. I made a mistake when translating typeof(T[0]) into more modern code. That caused supprising errors. Pasting the code bellow if anyone is interested (can probably be shortened), thanks for the help and quick response. import std.traits; import std.conv; import std.metastrings; template Tuple(T...) { alias T Tuple; } template opApplyType(T) { static if(isArray!T) alias Tuple!(size_t,ForeachType!T) opApplyType; else static if(isAssociativeArray!T) alias Tuple!(typeof(T.keys)[0],typeof(T.values)[0]) opApplyType; else static if(hasMember!(T,"opApply")) alias ParameterTypeTuple!(typeof(&T.opApply)) opApplyType; } template foreachType(T) { static if(is(opApplyType!(T) V)) { static if(is(opApplyType!(V[$-1]))) alias Tuple!(V[0..$-1],foreachType!(V[$-1])) foreachType; else alias V foreachType; } else { pragma(msg,"Failed to resolve type "); static assert(0,opApplyType!(T)); } } template DgArgs(T...) { static if(T.length) const char[] DgArgs="ref "~T[0].stringof~","~DgArgs! (T[1..$]); else const char[] DgArgs=""; } template DgType(T...) { mixin("alias int delegate("~DgArgs!(T)~") Type;"); } template opApplyParams(int i) { static if(i==0) const char[] opApplyParams=""; else const char[] opApplyParams=",p"~to!string(i)~opApplyParams!(i-1); } template opApplyRest(int i) { const char[] opApplyRest="foreach(p"~opApplyParams! (i)~";opApplyN(v))" ~"\n\tif(auto r=dg(i,p"~opApplyParams! (i)~"))" ~"\n\t\treturn r;"; } struct opApplyContext(T) { alias foreachType!(T) FT; mixin DgType!(FT) DG; T* a; int opApply(DG.Type dg) { //consider recursive mixin of delegate function //writefln("Begin opApplyN: ",DG.Type.stringof); static if(isArray!T) { //pragma(msg,"array"); static if(is(opApplyType!(typeof((*a)[0])) V)) { //pragma(msg,"branch"); foreach(i,v;*a) { //pragma(msg,V.stringof); //pragma(msg,DG.Type.stringof); //pragma(msg,typeof(&opApplyN(v).opApply).stringof); //pragma(msg,opApplyRest! (FT.length-2)); mixin(opApplyRest! (FT.length-2)); } } else { //pragma(msg,"leaf"); foreach(i,v;*a) if(auto r=dg(i,v)) return r; } } else static if(isAssociativeArray!(T)) { pragma(msg,"hash"); static assert(0,"Not Implemented"); } else static if(hasMember!(T,"opApply")) { pragma(msg,"opApply"); static assert(0,"Not Implemented"); } else { pragma(msg,"else"); static assert(0,"Not Implemented"); } return 0; } } opApplyContext!(T) opApplyN(T)(T c) { opApplyContext!(T) t; t.a=&c; return t; } opApplyContext!(T) opApplyN(T:T*)(T* c) { opApplyContext!(T) t; t.a=c; return t; }
Aug 25 2013