Thread overview
CT aggregate computations
Mar 30, 2017
Enigma
Mar 30, 2017
Adam D. Ruppe
Mar 30, 2017
Ali Çehreli
Mar 30, 2017
H. S. Teoh
Mar 31, 2017
drug
March 30, 2017
Is it possible to compute at compile time computations on a manifest constant that contains values(in a somewhat complex way, but that shouldn't matter)?

I am using foreach and it seems to be done dynamically as I can step through the code for each value and see them change. This tells me it is not done at compile time like it should be.

I might have something like


import std.meta, std.algorithm, std.stdio;
void main()
{
	enum X = [1,2,3,4,5];
	int y = 0;	
	foreach(x; X) // or foreach(x; aliasSeqOf!X), both iterate over y at run time according to the debugger.
	   y = max(x, y);
	
	writeln(y);
		
}

But I want it to be effectively the same as


import std.meta, std.algorithm, std.stdio;
void main()
{
	enum X = [1,2,3,4,5];
	int y = 5;	
	writeln(y);	
}

so y is computed at compile time. I'd rather not having to create some complex templates to handle it, which I think could be done using template recursion. I know of Map and such but will these compute completely at compile time or will be essentially be the same as the foreach loop?
March 30, 2017
On Thursday, 30 March 2017 at 18:21:43 UTC, Enigma wrote:
> I am using foreach and it seems to be done dynamically as I can step through the code for each value and see them change. This tells me it is not done at compile time like it should be.

Remember two facts:

1) CTFE is never done unless it specifically must be done

and

2) D does not have static foreach, it is just regular foreach


And a third warning:

* enum foo = [1,2,3]; makes foo work just like an array literal... which means it actually does a runtime allocation every time you reference it. Rarely what you actually want!


The answer is simple though: write an ordinary function that does your calculation and pass it an ordinary array, but set it to a static immutable array to force CTFE.

int getMax(int[] X) {
      int y = 0;
      foreach(x; X)
         y = max(x, y);
      return y;
}

void main() {
   enum y = getMax([1,2,3,4,5]); // safe for int
   static immutable y = getMax(...); // use that if return array
}



So you need to do a regular loop in a regular function, then assign the result of that regular function to enum or static.
March 30, 2017
On 03/30/2017 11:21 AM, Enigma wrote:
> Is it possible to compute at compile time computations on a manifest
> constant that contains values(in a somewhat complex way, but that
> shouldn't matter)?

You can do anything that you want as long as it's available at compile time. For example, you cannot interact with a user.

> I am using foreach and it seems to be done dynamically as I can step
> through the code for each value and see them change. This tells me it is
> not done at compile time like it should be.

D does not have an explicit way of requesting compile-time execution. It's done when it's needed at compile time:

- enum values

- static const values

- Template arguments

- Mixin code

In order to prove yourself that something is computed at compile time, just use pragma(msg).

> import std.meta, std.algorithm, std.stdio;
> void main()
> {
>     enum X = [1,2,3,4,5];

One big gotcha with enum arrays is that every place that you refer to X, a temporary array will be created dynamically. Only the manifest value of the array is computed at compile time. Try the following code and be surprised that it prints two different addresses:

    writeln(X.ptr);
    writeln(X.ptr);

(This issue does not apply to strings.)

So, what you want to do is to create an enum like the above, but use it only once at runtime to initialize another array, likely immutable, for your actual use.

// This is what the program will actually use
immutable int[] X;

auto calculateArray() {
    return [1,2,3,4,5];
}

// This is used only once to initialize X
private enum X_ = calculateArray();
pragma(msg, "Known at compile time: ", X_);

import std.algorithm: maxElement;
enum y = maxElement(X_);

shared static this() {
    X = X_;
}

void main() {
    pragma(msg, "Known at compile time: ", y);
}

Ali

March 30, 2017
On Thu, Mar 30, 2017 at 06:21:43PM +0000, Enigma via Digitalmars-d-learn wrote:
> Is it possible to compute at compile time computations on a manifest constant that contains values(in a somewhat complex way, but that shouldn't matter)?

Yes, see below.


> I am using foreach and it seems to be done dynamically as I can step through the code for each value and see them change. This tells me it is not done at compile time like it should be.

If you want something done at compile time, you have to ask for it. The usual way is to use something like `enum` that must be known at compile-time to force the compiler to run the computation through CTFE.


> I might have something like
> 
> 
> import std.meta, std.algorithm, std.stdio;
> void main()
> {
> 	enum X = [1,2,3,4,5];
> 	int y = 0;
> 	foreach(x; X) // or foreach(x; aliasSeqOf!X), both iterate over y at run
> time according to the debugger.
> 	   y = max(x, y);
> 
> 	writeln(y);
> 
> }

Here is how to do it:

	auto computeY(int[] data)
	{
		int y = 0;
		foreach (x; data)
			y = max(x,y);
		return y;
	}

	void main()
	{
		enum X = [1,2,3,4,5];
		enum y = computeY(X);	// N.B.: enum forces CTFE
		writeln(y);
	}


> But I want it to be effectively the same as
> 
> 
> import std.meta, std.algorithm, std.stdio;
> void main()
> {
> 	enum X = [1,2,3,4,5];
> 	int y = 5;
> 	writeln(y);
> }
> 
> so y is computed at compile time. I'd rather not having to create some complex templates to handle it, which I think could be done using template recursion.
[...]

You don't need template recursion unless you're doing something at the AST level.  For most computations you want done at "compile-time", you can just use CTFE.

Again, I see the term "compile-time" is misleading people. You may want to read the following (it's still a draft, but what's there should help clear things up):

	http://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time


T

-- 
Caffeine underflow. Brain dumped.
March 31, 2017
30.03.2017 21:59, H. S. Teoh via Digitalmars-d-learn пишет:
>
> 	http://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time
>
Really useful link, thank you very much!