www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - array depth template

reply "Saaa" <empty needmail.com> writes:
Is this a good way to get the depth of an array?

int getArrayDepth(T)(ref T array)
{
static if( is(T A:A[]) )
{
A arr;
return 1 + getArrayDepth(arr);
}
else
{
return 0;
}
return -1;
} 
Jun 11 2009
next sibling parent BCS <none anon.com> writes:
Hello Saaa,

 Is this a good way to get the depth of an array?
 
 int getArrayDepth(T)(ref T array)
 {
 static if( is(T A:A[]) )
 {
 A arr;
 return 1 + getArrayDepth(arr);
 }
 else
 {
 return 0;
 }
 return -1;
 }
I just posted this today http://www.dsource.org/projects/scrapple/browser/trunk/Serial/utill.d
Jun 11 2009
prev sibling parent reply Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jun 11, 2009 at 9:15 PM, Saaa<empty needmail.com> wrote:
 Is this a good way to get the depth of an array?

 int getArrayDepth(T)(ref T array)
 {
 static if( is(T A:A[]) )
 {
 A arr;
 return 1 + getArrayDepth(arr);
 }
 else
 {
 return 0;
 }
 return -1;
 }
It's kind of the right idea, but.. it's also kind of weird. template ArrayDepth(T: T[]) { const ArrayDepth = 1 + ArrayDepth!(T); } template ArrayDepth(T) { const ArrayDepth = 0; } This lets you get the depth of any array _type_, like ArrayDepth!(int[][]) gives 2.
Jun 11 2009
next sibling parent reply "Saaa" <empty needmail.com> writes:
 It's kind of the right idea, but.. it's also kind of weird.

 template ArrayDepth(T: T[]) { const ArrayDepth = 1 + ArrayDepth!(T); }
 template ArrayDepth(T)       { const ArrayDepth = 0; }

 This lets you get the depth of any array _type_, like
 ArrayDepth!(int[][]) gives 2.
Ah , that's how you make it do at compile time, using const. BCS also did it a bit like me (one template that is) I just didn't know you could also just pass the type :D Any advantage to using two? He also does : is( T B ==B[]) iso is( T B:B[] ) Any significant difference there?
Jun 11 2009
parent reply "Saaa" <empty needmail.com> writes:
Also, what's the advantage of explicitly defining it as a template? 
Jun 11 2009
parent reply Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jun 11, 2009 at 11:02 PM, Saaa<empty needmail.com> wrote:
 Any advantage to using two?
I just tend to prefer template specialization when doing type pattern matching. It works out better than is() in some cases.
 He also does :  is( T B ==B[])  iso  is( T B:B[] )
 Any significant difference there?
I'm.. not sure, in this case anyway. Normally == does strict type comparison while : does implicit type conversion, but in this case, is() is being (ab)used to pick apart a type rather than test one. I think it'll always return 'true' in either case if T is an array, so I don't think there's a functional difference.
 Also, what's the advantage of explicitly defining it as a template?
As opposed to what, implicitly defining it as a template? This question doesn't really make sense.
Jun 11 2009
parent reply "Saaa" <empty needmail.com> writes:
 Any advantage to using two?
I just tend to prefer template specialization when doing type pattern matching. It works out better than is() in some cases.
Looks very Haskell like :)
 He also does :  is( T B ==B[])  iso  is( T B:B[] )
 Any significant difference there?
I'm.. not sure, in this case anyway. Normally == does strict type comparison while : does implicit type conversion, but in this case, is() is being (ab)used to pick apart a type rather than test one. I think it'll always return 'true' in either case if T is an array, so I don't think there's a functional difference.
Implicit convertion sounds a bit dangerous, might start using == instead
 Also, what's the advantage of explicitly defining it as a template?
As opposed to what, implicitly defining it as a template? This question doesn't really make sense.
I mean, I was using a function template.
 template ArrayDepth(T: T[]) { const ArrayDepth = 1 + ArrayDepth!(T); }
 template ArrayDepth(T)       { const ArrayDepth = 0; }
The code looks a bit strange to me: ArrayDepth is both a (const) value and template name and where is the return value ?
Jun 11 2009
parent reply Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jun 11, 2009 at 11:45 PM, Saaa<empty needmail.com> wrote:

 I'm.. not sure, in this case anyway. =A0Normally =3D=3D does strict type
 comparison while : does implicit type conversion, but in this case,
 is() is being (ab)used to pick apart a type rather than test one. =A0I
 think it'll always return 'true' in either case if T is an array, so I
 don't think there's a functional difference.
Implicit convertion sounds a bit dangerous, might start using =3D=3D inst=
ead Um, there's no "one's better than the other." Don't overgeneralize on things you don't understand. Implicit conversion is necessary in some cases, and in others, exact comparison is needed.
 Also, what's the advantage of explicitly defining it as a template?
As opposed to what, implicitly defining it as a template? =A0This question doesn't really make sense.
I mean, I was using a function template.
A function template is just a function in a template. Templates can work just fine on their own. If you're manipulating types, there's really no need to get functions involved.
 template ArrayDepth(T: T[]) { const ArrayDepth =3D 1 + ArrayDepth!(T); }
 template ArrayDepth(T) =A0 =A0 =A0 { const ArrayDepth =3D 0; }
The code looks a bit strange to me: ArrayDepth is both a (const) value and template name and where is the ret=
urn
 value ?
See "Implicit Template Properties" here: http://www.digitalmars.com/d/1.0/template.html When you create a member in a template with the same name as the template, you can access it from the template without explicitly writing ArrayDepth!(int[]).ArrayDepth.
Jun 11 2009
parent "Saaa" <empty needmail.com> writes:
Um, there's no "one's better than the other."  Don't overgeneralize on
things you don't understand. Implicit conversion is necessary in some cases, and in others, exact comparison is needed. I didn't mean it like that, don't worry :) I mean, I apparently used implicit when I actually wanted explicit.
A function template is just a function in a template.  Templates can
work just fine on their own. If you're manipulating types, there's really no need to get functions involved. Check
See "Implicit Template Properties" here:
http://www.digitalmars.com/d/1.0/template.html Reading . .
When you create a member in a template with the same name as the
template, you can access it from the template without explicitly writing ArrayDepth!(int[]).ArrayDepth.
Jun 11 2009
prev sibling parent reply "Saaa" <empty needmail.com> writes:
 It's kind of the right idea, but.. it's also kind of weird.

 template ArrayDepth(T: T[]) { const ArrayDepth = 1 + ArrayDepth!(T); }
 template ArrayDepth(T)       { const ArrayDepth = 0; }

 This lets you get the depth of any array _type_, like
 ArrayDepth!(int[][]) gives 2.
Although I don't fully understand your code, I think I modified it correctly to get the base type of an array :) template BaseType(T: T[]) { const BaseType = BaseType!(T); } template BaseType(T) {const BaseType = T; }
Jun 11 2009
parent reply "Saaa" <empty needmail.com> writes:
 template BaseType(T: T[]) { const BaseType = BaseType!(T); }
 template BaseType(T) {const BaseType = T; }
.. else static if( std2.traits.isNumeric!( BaseType!(T) ) ) { .. ddata\ddata.d(192): template instance isNumeric!(int) does not match any template declaration ddata\ddata.d(192): Error: expression isNumeric!(int) is not constant or does not evaluate to a bool What am I doing wrong?
Jun 11 2009
parent reply Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Fri, Jun 12, 2009 at 12:04 AM, Saaa<empty needmail.com> wrote:
 template BaseType(T: T[]) { const BaseType = BaseType!(T); }
 template BaseType(T) {const BaseType = T; }
.. else static if( std2.traits.isNumeric!( BaseType!(T) ) ) { .. ddata\ddata.d(192): template instance isNumeric!(int) does not match any template declaration ddata\ddata.d(192): Error: expression isNumeric!(int) is not constant or does not evaluate to a bool What am I doing wrong?
Your template. Types are not values, you cannot declare a constant that is a type. You have to use alias instead: template BaseType(T: T[]) { alias BaseType!(T) BaseType; } template BaseType(T) { alias T BaseType; }
Jun 11 2009
parent "Saaa" <empty needmail.com> writes:
 Your template.  Types are not values, you cannot declare a constant
 that is a type.  You have to use alias instead:

 template BaseType(T: T[]) { alias BaseType!(T) BaseType; }
 template BaseType(T) { alias T BaseType; }
Erm, why did this print corretly? writefln(`BaseType = `, BaseType!(T).stringof ); btw. Thanks for everything !! It's nice to get some comments after a fews days of struggling with them templates :) I can now parse any numeric type (array) till depth 4; still haven't found a way to generalize this part :( private void Parse(T)(ref T parsed) { .. switch( depth ) { case 0: if( temp.length < index[depth] ) temp.length = temp.length * 2; break; static if( is(T A:A[][])) { case 1: if( temp[ index[0] ].length < index[depth] ) temp[index[0]].length = temp[index[0]].length * 2; break; } static if( is(T A:A[][][])) { case 2: if( temp[ index[0] ][ index[1] ].length < index[depth] ) temp[ index[0] ][ index[1] ].length = temp[ index[0] ][ index[1] ].length * 2; break; } default: assert(false); break; } .. }
Jun 11 2009