non-constant error for module AA"s

Lars T. Kyllingstad public at kyllingen.NOSPAMnet
Tue Jan 25 00:13:14 PST 2011


On Mon, 24 Jan 2011 10:45:03 -0500, Andrej Mitrovic wrote:

> Is this a bug?
> 
> import std.stdio;
> 
> string[string] values = ["abc":"abc", "def":"def"];
> 
> void main()
> {
>     string[string] values2 = ["abc":"abc", "def":"def"];
> }
> 
> 
> test.d(3): Error: non-constant expression ["abc":"abc","def":"def"]
> 
> What's non-constant about that expression?


My guess would be that using an AA literal is just syntax sugar for 
calling an AA construction function, and that said function isn't 
CTFEable.

When you specify an initial value for a global, that value must be a 
compile-time constant.  If it's not, as in this case, the correct thing 
to do is to use a module constructor:

  string[string] values;
  static this()
  {
      values = [ "abc":"abc", "def":"def" ];
  }

It is ONLY a good idea to use an enum array if you know you will be doing 
all lookups at compile time.  If the key you're looking for is just known 
at run time, the AA will be constructed anew for each lookup (I think), 
which is hideously expensive.

  enum string[string] values = [ "abc":"def", "ghi":"jkl" ];

  // This is fine, because it is done at compile time.
  // It's essentially the same as:  auto s = "def";
  auto s = values["abc"];

  // This is a no-no, because it evaluates to something
  // like:  auto aa = values; auto s = aa[key];
  auto key = "abc";
  auto s = values[key];

Here's an example program that demonstrates the difference.  On my 
machine, the enum AA version takes 22x longer than the "normal" AA 
version.


import std.datetime, std.stdio;


enum string[string] enumAA = [ "abc" : "abc", "def" : "def" ];

string[string] normalAA;
static this()
{
    normalAA = [ "abc" : "abc", "def" : "def" ];
}


void main()
{
    enum max = 10_000_000;
    StopWatch sw;
    string lookup1 = "abc";
    string lookup2 = "def";

    sw.start();
    foreach (i; 0 .. max)
    {
        auto a = enumAA[lookup1];
        auto b = enumAA[lookup2];
    }
    sw.stop();
    writeln(sw.peek().seconds);
    
    sw.reset();

    sw.start();
    foreach (i; 0 .. max)
    {
        auto a = normalAA[lookup1];
        auto b = normalAA[lookup2];
    }
    sw.stop();
    writeln(sw.peek().seconds);
}


More information about the Digitalmars-d-learn mailing list