Associative array literal is non-constant?

Artur Skawina art.08.09 at gmail.com
Mon Feb 6 12:31:54 PST 2012


On 02/06/12 20:46, H. S. Teoh wrote:
> 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.

The only thing i was worried about was the user not realizing the runtime
cost of such initializations. If the hash can be computed at compiletime
doing it like this is acceptable. Hmm. if the keys are not constants
expecting this operation to be cheap is not reasonable; so maybe you're
right that keeping the shorthand is OK. People will still write Q&D code
that omits const/immutable and not realize what actually happens until
it shows up in profiles. Right now, this will also be caught once you try
to make the AA const, but if that would become legal, the issue will be
even harder to spot.

artur


More information about the Digitalmars-d-learn mailing list