Thread overview
immutable int n = Test(); int[n] x;---- compiles, but __ctfe is false. How?
Feb 21, 2014
Gopan
Feb 21, 2014
FreeSlave
Feb 21, 2014
FreeSlave
Feb 21, 2014
Gopan
Feb 21, 2014
Ali Çehreli
Feb 23, 2014
Gopan
Feb 21, 2014
anonymous
Feb 23, 2014
Gopan
February 21, 2014
Attempting to learn CTFE, I tried the following test.

size_t counter;

uint Test()
{
	if (!__ctfe)
	{
		++counter;// This code is for execution at run time
	}
	return 2;
}

void main()
{
	writeln("counter = ", counter);
	
	immutable int n = Test();
	int[n] arr;
	writeln("arrary length = ", arr.length, " ; counter = ", counter);
}

output:
counter = 0
arrary length = 2 ; counter = 1

For array declaration to be successful, its size has to be known at compile time.  The above code compiles too.  But __ctfe seems to be false while performing Test().

Instead, if I write
	int[Test()] c;
	writeln("c.length = ", c.length, " ; counter = ", counter);
output is
counter = 0
c.length = 2 ; counter = 0

What is wrong in my mind?

Thanks,
Gopan
February 21, 2014
On Friday, 21 February 2014 at 13:38:58 UTC, Gopan wrote:
> Attempting to learn CTFE, I tried the following test.
>
> size_t counter;
>
> uint Test()
> {
> 	if (!__ctfe)
> 	{
> 		++counter;// This code is for execution at run time
> 	}
> 	return 2;
> }
>
> void main()
> {
> 	writeln("counter = ", counter);
> 	
> 	immutable int n = Test();
> 	int[n] arr;
> 	writeln("arrary length = ", arr.length, " ; counter = ", counter);
> }
>
> output:
> counter = 0
> arrary length = 2 ; counter = 1
>
> For array declaration to be successful, its size has to be known at compile time.  The above code compiles too.  But __ctfe seems to be false while performing Test().
>
> Instead, if I write
> 	int[Test()] c;
> 	writeln("c.length = ", c.length, " ; counter = ", counter);
> output is
> counter = 0
> c.length = 2 ; counter = 0
>
> What is wrong in my mind?
>
> Thanks,
> Gopan

Use enum n = Test() or make immutable n global variable i.e. place it before main.
February 21, 2014
Another strange thing:

import std.stdio;

uint Test()
{
    if (!__ctfe)
    {
        return 3;
    }
    return 2;
}



void main()
{
    immutable n = Test();
    int[n] arr;
    writeln("arrary length = ", arr.length, " ; n = ", n);
}

Output:
arrary length = 2 ; n = 3

When you think about it you understand that it's logically right behavior, but it's not acceptable in practice.
February 21, 2014
On Friday, 21 February 2014 at 13:38:58 UTC, Gopan wrote:
> Attempting to learn CTFE, I tried the following test.
>
> size_t counter;
>
> uint Test()
> {
> 	if (!__ctfe)
> 	{
> 		++counter;// This code is for execution at run time
> 	}
> 	return 2;
> }
>
> void main()
> {
> 	writeln("counter = ", counter);
> 	
> 	immutable int n = Test();

As this is a local variable, this is a runtime initialization, no
__ctfe here. Doesn't matter that it's immutable. It's
static/global vs local. So, this correctly does ++counter.

Make it static immutable n, and counter won't be incremented.

> 	int[n] arr;

Not sure if this should compile. n is a run-time value. It just
happens that it can be CTFE'd. A more problematic case:
---
void main()
{
	immutable n = __ctfe ? 1 : 2;
	int[n] a;
	assert(a.length == n); // fails, wat
}
---

> 	writeln("arrary length = ", arr.length, " ; counter = ", counter);
> }
>
> output:
> counter = 0
> arrary length = 2 ; counter = 1
>
> For array declaration to be successful, its size has to be known at compile time.  The above code compiles too.  But __ctfe seems to be false while performing Test().
>
> Instead, if I write
> 	int[Test()] c;
> 	writeln("c.length = ", c.length, " ; counter = ", counter);
> output is
> counter = 0
> c.length = 2 ; counter = 0
>
> What is wrong in my mind?
>
> Thanks,
> Gopan
February 21, 2014
On Friday, 21 February 2014 at 14:04:45 UTC, FreeSlave wrote:
> Another strange thing:
>
> import std.stdio;
>
> uint Test()
> {
>     if (!__ctfe)
>     {
>         return 3;
>     }
>     return 2;
> }
>
>
>
> void main()
> {
>     immutable n = Test();
>     int[n] arr;
>     writeln("arrary length = ", arr.length, " ; n = ", n);
> }
>
> Output:
> arrary length = 2 ; n = 3
>
> When you think about it you understand that it's logically right behavior, but it's not acceptable in practice.

It looks like 'immutable n = Test();' is executed during both compile time and runtime.  Is that what is happening?
February 21, 2014
On 02/21/2014 08:46 AM, Gopan wrote:

> On Friday, 21 February 2014 at 14:04:45 UTC, FreeSlave wrote:
>> Another strange thing:
>>
>> import std.stdio;
>>
>> uint Test()
>> {
>>     if (!__ctfe)
>>     {
>>         return 3;
>>     }
>>     return 2;
>> }
>>
>>
>>
>> void main()
>> {
>>     immutable n = Test();
>>     int[n] arr;
>>     writeln("arrary length = ", arr.length, " ; n = ", n);
>> }
>>
>> Output:
>> arrary length = 2 ; n = 3
>>
>> When you think about it you understand that it's logically right
>> behavior, but it's not acceptable in practice.
>
> It looks like 'immutable n = Test();' is executed during both compile
> time and runtime.  Is that what is happening?

Yes. The compiler needs the value of n at compile time so it evaluates it at compile time.

I agree that it is confusing but I feel like it is the responsibility of the programmer to ensure consistent behavior.

Ali

February 23, 2014
On Friday, 21 February 2014 at 17:04:45 UTC, Ali Çehreli wrote:
> On 02/21/2014 08:46 AM, Gopan wrote:
>
> > On Friday, 21 February 2014 at 14:04:45 UTC, FreeSlave wrote:
> >> Another strange thing:
> >>
> >> import std.stdio;
> >>
> >> uint Test()
> >> {
> >>     if (!__ctfe)
> >>     {
> >>         return 3;
> >>     }
> >>     return 2;
> >> }
> >>
> >>
> >>
> >> void main()
> >> {
> >>     immutable n = Test();
> >>     int[n] arr;
> >>     writeln("arrary length = ", arr.length, " ; n = ", n);
> >> }
> >>
> >> Output:
> >> arrary length = 2 ; n = 3
> >>
> >> When you think about it you understand that it's logically
> right
> >> behavior, but it's not acceptable in practice.
> >
> > It looks like 'immutable n = Test();' is executed during both
> compile
> > time and runtime.  Is that what is happening?
>
> Yes. The compiler needs the value of n at compile time so it evaluates it at compile time.

Thanks for confirming this, Ali.

> I agree that it is confusing but I feel like it is the responsibility of the programmer to ensure consistent behavior.
>
> Ali

February 23, 2014
On Friday, 21 February 2014 at 14:14:14 UTC, anonymous wrote:
> Not sure if this should compile. n is a run-time value. It just
> happens that it can be CTFE'd. A more problematic case:
> ---
> void main()
> {
> 	immutable n = __ctfe ? 1 : 2;
> 	int[n] a;
> 	assert(a.length == n); // fails, wat
> }

ie, seeing the declaration 'int[n] a;' one should not assume a.length is same as 'n' at runtime.  I would rather prefer getting a compilation error that n is not known at compile time and hence array declaration failed.

If this is eligible for a bugzilla, it is okay.  Otherwise, I am very disappointed.