digitalmars.D - Compile-time exceptions
- bearophile (30/30) Nov 24 2008 This is a generic example of a small function template (it's similar to ...
- Denis Koroskin (4/41) Nov 24 2008 This has already been discussed:
- Christopher Wright (4/5) Nov 24 2008 assert (!is (typeof (nest(1, 1, 1)))); // int is not callable
- bearophile (7/9) Nov 24 2008 Oh, right, that syntax isn't much elegant, but it seems to work, and it'...
- bearophile (7/8) Nov 25 2008 I have just used a static assert version of that in about one hundred pl...
- Christopher Wright (8/14) Nov 25 2008 I don't know what this is doing. That code fragment won't compile, and
- bearophile (9/13) Nov 25 2008 Sorry:
- Denis Koroskin (8/19) Nov 25 2008 Did you mean:
- bearophile (4/5) Nov 25 2008 Yes, of course :-)
- Christopher Wright (8/25) Nov 25 2008 I thought you could do this with an alias parameter, but perhaps I'm
This is a generic example of a small function template (it's similar to a function with the same name in Mathematica. It that returns the result of the callable 'func' applied n times to 'item'): TyItem nest(TyFun, TyItem)(TyFun func, TyItem item, int n) { static assert(IsCallable!(TyFun), "nest(): func must be a callable"); static assert(CastableTypes!(ReturnType!(TyFun), TyItem), "nest(): func must return a type castable to item."); if (n < 0) throw new ArgumentException("nestList(): n must be >= 0"); for (int i = 1; i <= n; i++) item = func(item); return item; } // End of nest() Its unit tests contain the following stuff too, because raising that exception is part of the user interface of that function: unittest { ... assert(Throws!(ArgumentException)(nest(&sin, 0.1, -1))); ... //nest("hello", 0.1, -1); // static asserts ... } (I'm waiting to have a better Throws!() in the std lib that doesn't require to be put into an assert()). But at the moment I haven't found ways to unit test the first two static asserts, so I just put tests in the unittest for them, and I comment them out to make the unittest run. That problem may be solved with a "static try" and "static catch", that work at compile time :-) (I think this isn't related with the Java static exceptions). static try deleg(); static catch (StaticAssert a) { ... } Bye, bearophile
Nov 24 2008
On Mon, 24 Nov 2008 13:15:36 +0300, bearophile <bearophileHUGS lycos.com> wrote:This is a generic example of a small function template (it's similar to a function with the same name in Mathematica. It that returns the result of the callable 'func' applied n times to 'item'): TyItem nest(TyFun, TyItem)(TyFun func, TyItem item, int n) { static assert(IsCallable!(TyFun), "nest(): func must be a callable"); static assert(CastableTypes!(ReturnType!(TyFun), TyItem), "nest(): func must return a type castable to item."); if (n < 0) throw new ArgumentException("nestList(): n must be >= 0"); for (int i = 1; i <= n; i++) item = func(item); return item; } // End of nest() Its unit tests contain the following stuff too, because raising that exception is part of the user interface of that function: unittest { ... assert(Throws!(ArgumentException)(nest(&sin, 0.1, -1))); ... //nest("hello", 0.1, -1); // static asserts ... } (I'm waiting to have a better Throws!() in the std lib that doesn't require to be put into an assert()). But at the moment I haven't found ways to unit test the first two static asserts, so I just put tests in the unittest for them, and I comment them out to make the unittest run. That problem may be solved with a "static try" and "static catch", that work at compile time :-) (I think this isn't related with the Java static exceptions). static try deleg(); static catch (StaticAssert a) { ... } Bye, bearophileThis has already been discussed: http://digitalmars.com/d/archives/digitalmars/D/static_try_catch_construct_would_be_helpful_66794.html
Nov 24 2008
bearophile wrote:But at the moment I haven't found ways to unit test the first two static asserts, so I just put tests in the unittest for them, and I comment them out to make the unittest run.assert (!is (typeof (nest(1, 1, 1)))); // int is not callable If you're using d2: assert (!__traits (compiles, nest(1, 1, 1)));
Nov 24 2008
Christopher Wright:assert (!is (typeof (nest(1, 1, 1)))); // int is not callableOh, right, that syntax isn't much elegant, but it seems to work, and it's doable. Thank you. I'll probably use it now and then. You can use it statically too :-) static assert (!is (typeof (nest(1, 2, 3)))); // int is not callableIf you're using d2:<Not yet. Bye, bearophile
Nov 24 2008
Christopher Wright Wrote:assert (!is (typeof (nest(1, 1, 1)))); // int is not callableI have just used a static assert version of that in about one hundred places in my dlibs, with good results, thank you :-) It has replaced lot of commented out and mostly useless lines of code with actual code that can spot problems at compile time. This begs for compiler (or standard lib) support, I think. On the topic of idioms: I may also use an idiom just shown to me by downs, to allow "passing" "function templates" to other functions: _sum { T opCall(T)(T[] array) { ... } } _sum sum; That's another situation where I think some built-in syntactic sugar can be useful. Do you have ideas regarding a possible syntax/statement? Bye, bearophile
Nov 25 2008
bearophile wrote:On the topic of idioms: I may also use an idiom just shown to me by downs, to allow "passing" "function templates" to other functions: _sum { T opCall(T)(T[] array) { ... } } _sum sum;I don't know what this is doing. That code fragment won't compile, and it isn't showing usage. Passing an instantiation of a function template is easy -- you just pass in a function. Passing a template requires an alias template parameter, I think. Virtual templates would allow you to use polymorphism in this case, but that's not going to be considered for quite some time, if at all.That's another situation where I think some built-in syntactic sugar can be useful. Do you have ideas regarding a possible syntax/statement? Bye, bearophile
Nov 25 2008
Christopher Wright Wrote:I don't know what this is doing. That code fragment won't compile, and it isn't showing usage.Sorry: struct _add { T opCall(T.init + T.init)(T x) { return x+x; } } _add add; Now you can give it to a function, without the need of specializing it for a type T first (you can't give the pointer to a template). (This may also be faster, because there isn't a delegate to call). (Haskell is statically typed and allows you do more complex things with a clean enough syntax).Virtual templates would allow you to use polymorphism in this case, but that's not going to be considered for quite some time, if at all.Can you explain? Bye, bearophile
Nov 25 2008
On Tue, 25 Nov 2008 15:28:53 +0300, bearophile <bearophile lycos.com> wrote:Christopher Wright Wrote:Did you mean: struct _add { typeof(A.init+B.init) opCall(A, B)(A a, B b) { return a + b; } } _add add; auto x = add(3, 0.1415926); ?I don't know what this is doing. That code fragment won't compile, and it isn't showing usage.Sorry: struct _add { T opCall(T.init + T.init)(T x) { return x+x; } } _add add;Now you can give it to a function, without the need of specializing it for a type T first (you can't give the pointer to a template). (This may also be faster, because there isn't a delegate to call). (Haskell is statically typed and allows you do more complex things with a clean enough syntax).Yes, it is a nice trick.
Nov 25 2008
Denis Koroskin:Did you mean:Yes, of course :-) Bye, bearophile
Nov 25 2008
bearophile wrote:Christopher Wright Wrote:I thought you could do this with an alias parameter, but perhaps I'm wrong. It's not the sort of thing I try to do, usually.I don't know what this is doing. That code fragment won't compile, and it isn't showing usage.Sorry: struct _add { T opCall(T.init + T.init)(T x) { return x+x; } } _add add; Now you can give it to a function, without the need of specializing it for a type T first (you can't give the pointer to a template). (This may also be faster, because there isn't a delegate to call). (Haskell is statically typed and allows you do more complex things with a clean enough syntax).does specialized code generation at runtime for each generic type it creates. D could do this with full templates, not just generics, and at compile time, but it'd require an extra compilation step before linking, most likely.Virtual templates would allow you to use polymorphism in this case, but that's not going to be considered for quite some time, if at all.Can you explain?Bye, bearophile
Nov 25 2008