View mode: basic / threaded / horizontal-split · Log in · Help
August 28, 2012
CTFE question
I have the following code:

------------------------------------

import std.stdio;
import std.metastrings;

pure int[] testCTFE(){
  int[] r;
  pragma(msg, "Testing CTFE");
  foreach(i; 0 .. 360){
    r ~= i;
    pragma(msg, Format!("Loop: %d",i));
  }
  pragma(msg, "Done CTFE test");
  return r;
}

immutable CTFEdata = testCTFE();

void main(string[] args){ }

----------------------------------

I expected this would compile and during compilation print:
Loop: 1 Loop:2, etc
However, I get a compilation error:

ctfe.d(9): Error: variable i cannot be read at compile time

Is this a bug or am I doing something wrong ??

Danny Arends
http://www.dannyarends.nl
August 28, 2012
Re: CTFE question
On Tuesday, 28 August 2012 at 11:13:40 UTC, Danny Arends wrote:
> Is this a bug or am I doing something wrong ??
>
> Danny Arends
> http://www.dannyarends.nl

You're doing something wrong, but I can see why the error message 
would confuse you.

Your problem is using those pragma(msg, ...) lines... They 
produce a message while something is being compiled, right? The 
CTFE function is ran _after_ it has been compiled. Hence i can't 
be read while the CTFE function is compiled.

So, to be clear, doing this:


-----

import std.stdio;
import std.metastrings;

pure int[] testCTFE(){
  int[] r;
  pragma(msg, "Testing CTFE");
  foreach(i; 0 .. 360){
    r ~= i;
    //pragma(msg, Format!("Loop: %d",i));
  }
  pragma(msg, "Done CTFE test");
  return r;
}

immutable CTFEdata = testCTFE();
immutable CTFEdata2 = testCTFE();

void main(string[] args){ }

----

Produces just one output:
Testing CTFE
Done CTFE test


Because the pragmas are done _as it's compiled_, not as it's ran 
(even though CTFE is done "at compile time").
August 28, 2012
Re: CTFE question
Ahhh I understand...

As a follow up, is it then possible to 'track' filling a
large enum / immutable on compile time by outputting a msg
every for ?

I'm generating rotation matrices for yaw, pitch and roll
at compile time which can take a long time depending on
how fine grained I create them.

Gr,
Danny Arends
http://www.dannyarends.nl

On Tuesday, 28 August 2012 at 11:29:32 UTC, Chris Cain wrote:
> On Tuesday, 28 August 2012 at 11:13:40 UTC, Danny Arends wrote:
>> Is this a bug or am I doing something wrong ??
>>
>> Danny Arends
>> http://www.dannyarends.nl
>
> You're doing something wrong, but I can see why the error 
> message would confuse you.
>
> Your problem is using those pragma(msg, ...) lines... They 
> produce a message while something is being compiled, right? The 
> CTFE function is ran _after_ it has been compiled. Hence i 
> can't be read while the CTFE function is compiled.
>
> So, to be clear, doing this:
>
>
> -----
>
> import std.stdio;
> import std.metastrings;
>
> pure int[] testCTFE(){
>   int[] r;
>   pragma(msg, "Testing CTFE");
>   foreach(i; 0 .. 360){
>     r ~= i;
>     //pragma(msg, Format!("Loop: %d",i));
>   }
>   pragma(msg, "Done CTFE test");
>   return r;
> }
>
> immutable CTFEdata = testCTFE();
> immutable CTFEdata2 = testCTFE();
>
> void main(string[] args){ }
>
> ----
>
> Produces just one output:
> Testing CTFE
> Done CTFE test
>
>
> Because the pragmas are done _as it's compiled_, not as it's 
> ran (even though CTFE is done "at compile time").
August 28, 2012
Re: CTFE question
On Tuesday, 28 August 2012 at 11:39:20 UTC, Danny Arends wrote:
> Ahhh I understand...
>
> As a follow up, is it then possible to 'track' filling a
> large enum / immutable on compile time by outputting a msg
> every for ?
>
> I'm generating rotation matrices for yaw, pitch and roll
> at compile time which can take a long time depending on
> how fine grained I create them.

I'm pretty sure there isn't. However, if you're just trying to 
develop/test your algorithm, you could write a program that runs 
it as a normal function (and just use writeln) as you develop it. 
After it's done, you remove the writelns, mark the function as 
pure and it should work exactly the same in CTFE.
August 28, 2012
Re: CTFE question
On Tuesday, 28 August 2012 at 12:07:07 UTC, Chris Cain wrote:
> On Tuesday, 28 August 2012 at 11:39:20 UTC, Danny Arends wrote:
> I'm pretty sure there isn't. However, if you're just trying to 
> develop/test your algorithm, you could write a program that 
> runs it as a normal function (and just use writeln) as you 
> develop it. After it's done, you remove the writelns, mark the 
> function as pure and it should work exactly the same in CTFE.

Well it just seems some compilation runs take way longer (and 
more memory)
then others..Googling I found that I just got to wait for:

https://github.com/D-Programming-Language/dmd/pull/692

to be accepted. Seems a bit strange that a discussion about yes/no
newline is keeping this from getting into DMD.

Just basic ctfewrite support would help me a lot.

Gr,
Danny Arends
August 28, 2012
Re: CTFE question
Danny Arends:

> Seems a bit strange that a discussion about yes/no
> newline is keeping this from getting into DMD.

The ending newline is bad, because it unnecessarily kills some
use cases for this feature.

But I think the newline is not what is keeping it out of DMD.
It's just there are about a hundred open patches, and Walter is
currently implementing 64bits on Windows.

Bye,
bearophile
August 28, 2012
Re: CTFE question
On Tue, Aug 28, 2012 at 2:07 PM, Chris Cain <clcain@uncg.edu> wrote:
> On Tuesday, 28 August 2012 at 11:39:20 UTC, Danny Arends wrote:
>>
>> Ahhh I understand...
>>
>> As a follow up, is it then possible to 'track' filling a
>> large enum / immutable on compile time by outputting a msg
>> every for ?
>>
>> I'm generating rotation matrices for yaw, pitch and roll
>> at compile time which can take a long time depending on
>> how fine grained I create them.
>
>
> I'm pretty sure there isn't. However, if you're just trying to develop/test
> your algorithm, you could write a program that runs it as a normal function
> (and just use writeln) as you develop it. After it's done, you remove the
> writelns, mark the function as pure and it should work exactly the same in
> CTFE.

Godd adivce, except beware of using ++ and --, they don't work at
compile-time. I'm regularly caught unaware by this, particularly while
looping.


Danny is also using 0..360, which is a runtime value. There exists a
compile-time version of foreach which is automatically invoked
whenever you use foreach on a compile-time 'range' (aka, typetuple)

So:

template Loop(T...)
{
   /* some code */
   foreach(i,Type; T)
       pragma(msg, i);
}

will work.

So, a way to get what the OP wanted is to create a tuple of the
required length. Since integers are valid template arguments, we can
use them directly like this:

template staticRange(uint upto)
{
   static if (upto == 0)
       alias TypeTuple!() staticRange;
   else
       alias TypeTuple!(staticRange!(upto-1), upto-1) staticRange;
}

So staticRange!3 is the tuple 0,1,2. (staticRange!0 is empty)
You can foreach on it:

pure int[] testCTFE(){
 int[] r;
 pragma(msg, "Testing CTFE");

 foreach(i; staticRange!360){
   r ~= i;
   pragma(msg, i);
 }

 pragma(msg, "Done CTFE test");
 return r;
}


Of course, that means knowing the upper value at compile-time.
September 03, 2012
Re: CTFE question
On 28/08/12 19:40, Philippe Sigaud wrote:
> On Tue, Aug 28, 2012 at 2:07 PM, Chris Cain <clcain@uncg.edu> wrote:
>> On Tuesday, 28 August 2012 at 11:39:20 UTC, Danny Arends wrote:
>>>
>>> Ahhh I understand...
>>>
>>> As a follow up, is it then possible to 'track' filling a
>>> large enum / immutable on compile time by outputting a msg
>>> every for ?
>>>
>>> I'm generating rotation matrices for yaw, pitch and roll
>>> at compile time which can take a long time depending on
>>> how fine grained I create them.
>>
>>
>> I'm pretty sure there isn't. However, if you're just trying to develop/test
>> your algorithm, you could write a program that runs it as a normal function
>> (and just use writeln) as you develop it. After it's done, you remove the
>> writelns, mark the function as pure and it should work exactly the same in
>> CTFE.
>
> Godd adivce, except beware of using ++ and --, they don't work at
> compile-time. I'm regularly caught unaware by this, particularly while
> looping.

Really? That's scary. Is there a bug report for this?
September 03, 2012
Re: CTFE question
On Mon, Sep 3, 2012 at 1:27 PM, Don Clugston <dac@nospam.com> wrote:


>> Godd adivce, except beware of using ++ and --, they don't work at
>> compile-time. I'm regularly caught unaware by this, particularly while
>> looping.
>
>
> Really? That's scary. Is there a bug report for this?

I re-tried this and I was mistaken: it's not ++ or --, it's changing
an iteration index at compile-time. My bad.

int[] indices(string s)
{
   int[] store;
   foreach(i,ch; s[0..$-1])
   {
       store ~= i;
       if (s[i..i+2] == "aa")
           i += 1; // also ++i or i++, no difference here
   }
   return store;
}

void main()
{
   enum result1 = indices("aaabc");
   auto result2 = indices("aaabc");

   writeln(result1); // [0,1,2,3]
   writeln(result2); // [0,2,3]
}

I know changing 'i' while iterating is not a good idea, but at least
in this case, CT-executed and RT-execution give a different result.
All my other tests with ++ and -- give correct results, sorry for the
bad publicity.

Worth a bug report?
September 03, 2012
Re: CTFE question
Philippe Sigaud:

> Worth a bug report?

Yeah. CTFE must give the same results when CTFE works.

A simpler test case for Bugzilla:

import std.stdio;
int[] foo(int[] data) {
     foreach (i, ref x; data) {
         x++;
         i++;
     }
     return data;
}
void main() {
    enum result1 = foo([10, 20, 30, 40]);
    auto result2 = foo([10, 20, 30, 40]);
    writeln(result1); // [11, 21, 31, 41]
    writeln(result2); // [11, 20, 31, 40]
}

Bye,
bearophile
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home