Associative array literal is non-constant?

H. S. Teoh hsteoh at quickfur.ath.cx
Mon Feb 6 11:46:00 PST 2012


On Sat, Feb 04, 2012 at 03:41:04PM +0100, Artur Skawina wrote:
[...]
> Consider the implementation, ie what you have to do to make const AAs
> work...
> 
> I think I'd prefer them to be distinct types, that do not implicitly
> convert to the non-const variant. Then the compiler is free to
> implement them differently, eg by picking a perfect hash, ensuring
> there are no collisions etc.  This would let you use them for fast
> local lookups, which is probably what most use cases of const AAs are.

I agree. I think it makes sense to have them as distinct types,
otherwise it will add a lot of complication since one expects const AA's
to be in a read-only data segment, but the current implementation
expects AA's to be on the heap.


> And if you assign it to another AA, the new one is initialized at
> runtime from the values in the const AA. Which (runtime init) is the
> only way possible currently. It shouldn't happen implicitly because
> for larger arrays the conversion could be expensive.

I'm OK with no implicit conversion, as long as explicit copying is
allowed (with the understanding that it may be costly).

I was thinking this may introduce potential problems with the assignment
operator =, but after some thought I think it should be OK:

If you write "X = Y" where Y is a const AA, then X must also be const
(type system requirement), and so it's OK to put const AA's in a
read-only data segment, since X will just become an alias of Y but the
user can't change the AA.

To copy a const AA to a non-const AA, you'd have to write "X = Y.dup",
which is also OK if .dup always returns a dynamic (non-const) AA.


> Defining a non-const AA initialized from a literal (like in the quoted
> examples above) is the non-obvious case. If nothing modifies the array
> and it does not leave the scope everything's fine. But if one of these
> things happens, doing the init/conversion at runtime might not be what
> the user expects. So keeping mutable AAs initialized from literals
> illegal would probably be the best thing.

I'm on the fence about this. I think it would be *very* useful if you
could write:

	int[string] X = ["a":1, "b":2, "c":3];

and have the compiler generate code to initialize X at runtime. I don't
think this should be translated as storing the literal in const space
and then doing an implicit .dup; the compiler should be able to infer
that since the literal is being assigned to a non-const AA, it should
generate code to construct the literal on the heap instead.

In other words, this:

	const int[string] X = ["a":1, "b":2, ...];

produces a compile-time AA stored in the program's read-only data
segment, whereas:

	int[string] X = ["a":1, "b":2, ...];

does not produce anything on the data segment, but is simply shorthand
for:

	int[string] X;
	X["a"] = 1;
	X["b"] = 2;
	...

Being able to initialize AA's from literals at runtime is a very
important feature, IMHO.

As for what type the literal should be by default:

	auto X = ["a":1, "b":2, ...];

I think typeof(X) should be const int[string].


T

-- 
When solving a problem, take care that you do not become part of the problem.


More information about the Digitalmars-d-learn mailing list