digitalmars.D - Semantics of mixed CT and RT statements
- Timoses (50/50) Dec 21 2018 I've just had the idea of mixing both `static` and "RT"
- Rubn (16/75) Dec 21 2018 Don't really see the point, the following will always be true
- Timoses (4/19) Dec 21 2018 This wouldn't print "1" in case T is != SomeType. Hence `static
- NaN (8/21) Dec 22 2018 Just do
- Timoses (31/40) Dec 22 2018 I'm not asking for "How to do this now?". I'm just communicating
- Neia Neutuladh (10/16) Dec 22 2018 An optimizer can very easily optimize this:
- Timoses (7/16) Dec 23 2018 Good point. I guess that eliminates the need for something like
- Neia Neutuladh (23/24) Dec 23 2018 bool foo(T)(T t) if (is(T == int) || is(T == string))
- NaN (4/19) Dec 24 2018 static if gives you a guarantee it'll be evaluated at run time
- NaN (2/7) Dec 24 2018 I meant at "compile time" oops
I've just had the idea of mixing both `static` and "RT" statements: void foo (T)(bool b) { static if (is(T == SomeType)) || if (b) { // Called when T is of type SomeType // otherwise, use `if (b)` for runtime to decide // fate of this block's execution assert(is(T == SomeType) || b); writeln("1"); } else static if (is(T == SomeOtherType)) && if (b) { // Called when T is of type SomeOtherType // AND when b is true assert(is(T == SomeOtherType) && b); writeln("2"); } } foo!SomeType(false); // prints 1 foo!SomeOtherType(false); // prints nothing foo!SomeOtherType(true); // prints 2 static if (A) || if (B): Only ever check B at run-time when A is false at compile-time static (A) && if (B): Check B at run-time if and only if A holds true at compile-time. And here both variants (as had to be implemented currently versus the shorter "mixed" variant) // Current static if (is(T == SomeType)) // do A if (b) // do A static if (is(T == SomeOtherType)) { if (b) // do B } // vs "Mixed" static if (is(T == SomeType)) || if (b) // do A static if (is(T == SomeOtherType)) && if (b) // do B I don't have a specific use case at hand. I believe it could help reduce code duplication in some situations; apparently more so for the `||` variant, as the `&&` variant can be rewritten as: static if (Cond1) if (Cond2) and works already. What do you think?
Dec 21 2018
On Saturday, 22 December 2018 at 03:35:56 UTC, Timoses wrote:I've just had the idea of mixing both `static` and "RT" statements: void foo (T)(bool b) { static if (is(T == SomeType)) || if (b) { // Called when T is of type SomeType // otherwise, use `if (b)` for runtime to decide // fate of this block's execution assert(is(T == SomeType) || b); writeln("1"); } else static if (is(T == SomeOtherType)) && if (b) { // Called when T is of type SomeOtherType // AND when b is true assert(is(T == SomeOtherType) && b); writeln("2"); } } foo!SomeType(false); // prints 1 foo!SomeOtherType(false); // prints nothing foo!SomeOtherType(true); // prints 2 static if (A) || if (B): Only ever check B at run-time when A is false at compile-time static (A) && if (B): Check B at run-time if and only if A holds true at compile-time. And here both variants (as had to be implemented currently versus the shorter "mixed" variant) // Current static if (is(T == SomeType)) // do A if (b) // do A static if (is(T == SomeOtherType)) { if (b) // do B } // vs "Mixed" static if (is(T == SomeType)) || if (b) // do A static if (is(T == SomeOtherType)) && if (b) // do B I don't have a specific use case at hand. I believe it could help reduce code duplication in some situations; apparently more so for the `||` variant, as the `&&` variant can be rewritten as: static if (Cond1) if (Cond2) and works already. What do you think?Don't really see the point, the following will always be true because of the static if.static if (is(T == SomeType)) || if (b) { // Called when T is of type SomeType // otherwise, use `if (b)` for runtime to decide // fate of this block's execution assert(is(T == SomeType) || b); writeln("1"); }You don't need to do another is() inside of the assert, as it is guaranteed to be true. Just put the logic in the static if like normal. static if( is(T== SomeType) ) { // runtime condition if( true || b ) // just becomes true writeln("1"); } else static if( is (T == SomeOtherType ) ) { if( b ) { writeln("2"); } }
Dec 21 2018
On Saturday, 22 December 2018 at 03:51:58 UTC, Rubn wrote:You don't need to do another is() inside of the assert, as it is guaranteed to be true. Just put the logic in the static if like normal. static if( is(T== SomeType) ) { // runtime condition if( true || b ) // just becomes true writeln("1"); }This wouldn't print "1" in case T is != SomeType. Hence `static if || if`. Note that the idea of `static if || if` does not exist (afaik):static if (A) || if (B): Only ever check B at run-time when A is false at compile-timeelse static if( is (T == SomeOtherType ) ) { if( b ) { writeln("2"); } }
Dec 21 2018
On Saturday, 22 December 2018 at 04:02:46 UTC, Timoses wrote:On Saturday, 22 December 2018 at 03:51:58 UTC, Rubn wrote:Just do if ((is(T == SomeType)) || (b)) First bit will be evaluated at compile time but or-ed with 'b' at runtime. The point is if you want the whole thing evaluated in one rather than in sequence, then the whole expression is dependant on a runtime variable, which makes using static if on half of it wrong.You don't need to do another is() inside of the assert, as it is guaranteed to be true. Just put the logic in the static if like normal. static if( is(T== SomeType) ) { // runtime condition if( true || b ) // just becomes true writeln("1"); }This wouldn't print "1" in case T is != SomeType. Hence `static if || if`.
Dec 22 2018
On Saturday, 22 December 2018 at 10:29:08 UTC, NaN wrote:Just do if ((is(T == SomeType)) || (b)) First bit will be evaluated at compile time but or-ed with 'b' at runtime. The point is if you want the whole thing evaluated in one rather than in sequence, then the whole expression is dependant on a runtime variable, which makes using static if on half of it wrong.I'm not asking for "How to do this now?". I'm just communicating an idea and am curious about your thoughts about it. The point is thatif ((is(T == SomeType)) || (b))misses the point of statically generating content IN CASE a condition is true at compile time. static if (T) // do A else if (b) // this already looks a bit like mixing static and run-time // do A The intention is to only do a check of b at run-time when T is false. If T is true, there is no need to check anything at run-time. However, the above has redundant duplicate statement '// do A'. Hence: Mixing static if and RT sounds alluring (the syntax is made up, but tells the story, I believe. Got a better idea?): static if (T) || if (b) // do A The ability of D to write generic code with static statements is amazing already. The question is: Could it be even richer and swifter? The case for the following (again: made up syntax!) static if (T) && if (b) // do A equals the very short static if (T) if (b) // do A This thread is merely of explorative nature and does not suggest any concrete improvements or nags about lack of any existing features.
Dec 22 2018
On Sun, 23 Dec 2018 00:52:23 +0000, Timoses wrote:The point is thatAn optimizer can very easily optimize this: // T is SomeType if (is(T == SomeType) || b) doStuff; to remove the if statement. So from that perspective, no need to worry about it. The sticky bit is that a runtime check needs both paths to typecheck, so if you're mixing metaprogramming with runtime logic, some cases might be weird. I've never needed to do that.if ((is(T == SomeType)) || (b))misses the point of statically generating content IN CASE a condition is true at compile time.
Dec 22 2018
On Sunday, 23 December 2018 at 02:58:30 UTC, Neia Neutuladh wrote:An optimizer can very easily optimize this: // T is SomeType if (is(T == SomeType) || b) doStuff; to remove the if statement. So from that perspective, no need to worry about it.Good point. I guess that eliminates the need for something like "static if (T) || if (b)". However, going along that line, why does D even have "static if"? We could simply use "if" everywhere and let the compiler take care of it. Perhaps it's more a question of expressiveness.The sticky bit is that a runtime check needs both paths to typecheck, so if you're mixing metaprogramming with runtime logic, some cases might be weird.Do you have an example? I'm not quite sure I get what you mean.I've never needed to do that.
Dec 23 2018
On Mon, 24 Dec 2018 01:08:57 +0000, Timoses wrote:Do you have an example? I'm not quite sure I get what you mean.bool foo(T)(T t) if (is(T == int) || is(T == string)) { if (is(T == int) || t == T.init) return false; else return t.startsWith("something"); } This is a pretty contrived example, but the is() constrains the type in the else clause. The else clause has to type-check for both int and string, and it doesn't. The fix is straightforward: detangle the runtime and compile-time conditions. bool foo(T)(T t) if (is(T == int) || is(T == string)) { static if (is(T == int)) { return false; } else // T == string { if (t == T.init) return false; return t.startsWith("something"); } }
Dec 23 2018
On Monday, 24 December 2018 at 01:08:57 UTC, Timoses wrote:On Sunday, 23 December 2018 at 02:58:30 UTC, Neia Neutuladh wrote:static if gives you a guarantee it'll be evaluated at run time and the dead code branch pruned away. Not sure if the scoping also has different semantics vs a regular if.An optimizer can very easily optimize this: // T is SomeType if (is(T == SomeType) || b) doStuff; to remove the if statement. So from that perspective, no need to worry about it.Good point. I guess that eliminates the need for something like "static if (T) || if (b)". However, going along that line, why does D even have "static if"? We could simply use "if" everywhere and let the compiler take care of it. Perhaps it's more a question of expressiveness.
Dec 24 2018
On Monday, 24 December 2018 at 10:16:59 UTC, NaN wrote:On Monday, 24 December 2018 at 01:08:57 UTC, Timoses wrote:I meant at "compile time" oopsOn Sunday, 23 December 2018 at 02:58:30 UTC, Neia Neutuladhstatic if gives you a guarantee it'll be evaluated at run time and the dead code branch pruned away. Not sure if the scoping also has different semantics vs a regular if.
Dec 24 2018