Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 22, 2018 Semantics of mixed CT and RT statements | ||||
---|---|---|---|---|
| ||||
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? |
December 22, 2018 Re: Semantics of mixed CT and RT statements | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timoses | 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"); } } |
December 22, 2018 Re: Semantics of mixed CT and RT statements | ||||
---|---|---|---|---|
| ||||
Posted in reply to Rubn | 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-time > else static if( is (T == SomeOtherType ) ) { > if( b ) { > writeln("2"); > } > } |
December 22, 2018 Re: Semantics of mixed CT and RT statements | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timoses | On Saturday, 22 December 2018 at 04:02:46 UTC, Timoses wrote:
> 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`.
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.
|
December 23, 2018 Re: Semantics of mixed CT and RT statements | ||||
---|---|---|---|---|
| ||||
Posted in reply to NaN | 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 that > if ((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. |
December 23, 2018 Re: Semantics of mixed CT and RT statements | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timoses | On Sun, 23 Dec 2018 00:52:23 +0000, Timoses wrote:
> The point is that
>
>> if ((is(T == SomeType)) || (b))
>
> misses the point of statically generating content IN CASE a condition is true at compile time.
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.
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.
|
December 24, 2018 Re: Semantics of mixed CT and RT statements | ||||
---|---|---|---|---|
| ||||
Posted in reply to Neia Neutuladh | 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. |
December 24, 2018 Re: Semantics of mixed CT and RT statements | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timoses | 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");
}
}
|
December 24, 2018 Re: Semantics of mixed CT and RT statements | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timoses | 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:
>>
>> 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.
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.
|
December 24, 2018 Re: Semantics of mixed CT and RT statements | ||||
---|---|---|---|---|
| ||||
Posted in reply to NaN | On Monday, 24 December 2018 at 10:16:59 UTC, NaN wrote:
> On Monday, 24 December 2018 at 01:08:57 UTC, Timoses wrote:
>> On Sunday, 23 December 2018 at 02:58:30 UTC, Neia Neutuladh
>
>
> 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.
I meant at "compile time" oops
|
Copyright © 1999-2021 by the D Language Foundation