digitalmars.D.learn - Unittests, templates
- bearophile (112/112) Oct 30 2008 I like to test all my functions, are there ways to unit test nested func...
- Bill Baxter (6/28) Oct 30 2008 I think this one should work. IFTI should be able to tease apart S to
- bearophile (5/7) Oct 30 2008 Trying it again it works! :-)
I like to test all my functions, are there ways to unit test nested functions? void foo() { int add(int x, int y) { return x + y; } unittest { // found 'unittest' instead of statement assert(add(10, 20) == 30); } } unittest { assert(foo.add(10, 20) == 30); // Error: no property 'add' for type 'void' } void main() {} If currently there's no way, I think it can be good to add to the language some way to test them. ---------------------- This is a question regarding templates. Let's say I have a simple struct template that is specified by an integer: struct S(int N) { int[N] a; } Now I'd like to write a function that takes a S, and for example prints the integers of S.a separated by a space (I don't care of the extra space at the end). This is easy to to in Haskell because it has type classes, but it's less easy to do in D (I don't know if type classes can be introduced into the D type system): http://en.wikipedia.org/wiki/Type_class This is a simple solution, but it compiles only if N == 2, so I'd like something more general: void printS1(S!(2) s) { foreach (el; s.a) put(el, " "); putr(); } This is general, a function template, but it requires you to specify N: void printS2(int N)(S!(N) s) { foreach (el; s.a) put(el, " "); putr(); } You have to call it for example like this: printS2!(s.a.length)(s); The following way ignores S, and just looks if the given type T has the requires qualities: void printS3(T)(T s) { static assert(is(T == struct) && (T.tupleof.length == 1) && is(typeof(T.a)) && is(ArrayType1!(typeof(T.a)) == int) ); foreach (el; s.a) put(el, " "); putr(); } (Where ArrayType1 gives the type of the items of T.a). printS3 isn't strict enough, because it accepts all typedef-ined types as long as they have that qualities. And if you change S a little, you have to change lot of code. The following doesn't work, I don't know why: void printSX(T)(T s) { static assert ( is(T == S) ); ... So this is more strict, but requires more RAM during compilation, and it doesn't accept N > 13: void printS4(T)(T s) { //static assert (is(T == S), "printS4: err"); // doesn't work static assert (IsType!(T, S!(0), S!(1), S!(2), S!(3), S!(4), S!(5), S!(6), S!(7), S!(8), S!(9), S!(10), S!(11), S!(12), S!(13) ), "printS4: err"); foreach (el; s.a) put(el, " "); putr(); } Of course that can be generalized, up to N =~ 2930 but it requires lot of RAM and some compilation time, so this can't be the way to go: template IsTN(alias TN, T, int N=0) { static if (N >= 2900 || N < 0) // 2900 is an arbitrary high value const bool IsTN = false; else static if ( is(T == TN!(N)) ) const bool IsTN = true; else const bool IsTN = IsTN!(TN, T, N+1); } void printS5(T)(T s) { static assert (IsTN!(S, T), "printS5: err"); foreach (el; s.a) put(el, " "); putr(); } To reduce the RAM used I have tried to use a CT function, but it doesn't work: bool isTN(alias TN, T)() { // doesn't work int i = 0; while ( is(T == TN!(i)) ) {} return true; } void printS6(T)(T s) { static assert (isTN!(S, T)(), "printS6: err"); foreach (el; s.a) put(el, " "); putr(); } I have tried with a recursive CT function, but it doesn't work still (maybe there are ways to make it run): bool isTN2(alias TN, T)(int n=0) { if (n >= 2900 || n < 0) return false; else if ( is(T == TN!(n)) ) return true; else return IsTN2!(TN, T)(n+1); } void printS8(T)(T s) { static assert (isTN2!(S, T)(), "printS6: err"); foreach (el; s.a) put(el, " "); putr(); } In the end changing totally approch it works and uses little RAM, but is this a good solution? void printS7(T)(T s) { static assert (S.stringof == "S(int N)", "printS7: err"); foreach (el; s.a) put(el, " "); putr(); } Bye, bearophile
Oct 30 2008
On Fri, Oct 31, 2008 at 11:57 AM, bearophile <bearophileHUGS lycos.com> wrote:This is a question regarding templates. Let's say I have a simple struct template that is specified by an integer: struct S(int N) { int[N] a; } Now I'd like to write a function that takes a S, and for example prints the integers of S.a separated by a space (I don't care of the extra space at the end). This is easy to to in Haskell because it has type classes, but it's less easy to do in D (I don't know if type classes can be introduced into the D type system): http://en.wikipedia.org/wiki/Type_class This is a simple solution, but it compiles only if N == 2, so I'd like something more general: void printS1(S!(2) s) { foreach (el; s.a) put(el, " "); putr(); } This is general, a function template, but it requires you to specify N: void printS2(int N)(S!(N) s) { foreach (el; s.a) put(el, " "); putr(); } You have to call it for example like this: printS2!(s.a.length)(s);I think this one should work. IFTI should be able to tease apart S to match the int. If it doesn't work, it seems like a bug to me. Actually I seem to remember a bug like this in the DB, but I couldn't find it just now. I was also thinking it was marked fixed. --bb
Oct 30 2008
Bill Baxter:I think this one should work. IFTI should be able to tease apart S to match the int.Trying it again it works! :-) Thank you. Bye, bearophile
Oct 30 2008