www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - immutable int n = Test(); int[n] x;---- compiles, but __ctfe is false.

reply "Gopan" <gggopan gmail.com> writes:
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
Feb 21 2014
next sibling parent reply "FreeSlave" <freeslave93 gmail.com> writes:
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.
Feb 21 2014
parent reply "FreeSlave" <freeslave93 gmail.com> writes:
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.
Feb 21 2014
parent reply "Gopan" <gggopan gmail.com> writes:
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?
Feb 21 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Feb 21 2014
parent "Gopan" <gggopan gmail.com> writes:
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
Feb 23 2014
prev sibling parent reply "anonymous" <anonymous example.com> writes:
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
Feb 21 2014
parent "Gopan" <gggopan gmail.com> writes:
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.
Feb 23 2014