| Thread overview | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 24, 2008 Compile-time exceptions | ||||
|---|---|---|---|---|
| ||||
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
| ||||
November 24, 2008 Re: Compile-time exceptions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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, > bearophile This has already been discussed: http://digitalmars.com/d/archives/digitalmars/D/static_try_catch_construct_would_be_helpful_66794.html | |||
November 24, 2008 Re: Compile-time exceptions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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)));
| |||
November 24, 2008 Re: Compile-time exceptions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | Christopher Wright: > assert (!is (typeof (nest(1, 1, 1)))); // int is not callable Oh, 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 callable >If you're using d2:< Not yet. Bye, bearophile | |||
November 25, 2008 Re: Compile-time exceptions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | Christopher Wright Wrote:
> assert (!is (typeof (nest(1, 1, 1)))); // int is not callable
I 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
| |||
November 25, 2008 Re: Compile-time exceptions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 | |||
November 25, 2008 Re: Compile-time exceptions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | 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 | |||
November 25, 2008 Re: Compile-time exceptions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Tue, 25 Nov 2008 15:28:53 +0300, bearophile <bearophile@lycos.com> wrote: > 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; > 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); ? > 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. | |||
November 25, 2008 Re: Compile-time exceptions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Denis Koroskin | Denis Koroskin:
> Did you mean:
Yes, of course :-)
Bye,
bearophile
| |||
November 26, 2008 Re: Compile-time exceptions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile wrote: > 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). 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. >> 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? Like generics in C#. Java's just hiding casts with its generics, but C# 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. > Bye, > bearophile | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply