Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
February 04, 2012 Re: Associative array literal is non-constant? | ||||
---|---|---|---|---|
| ||||
On Fri, Feb 03, 2012 at 10:18:18PM -0800, H. S. Teoh wrote: > Why does the following code give a compiler error? > > static int[string] table = ["abc":1, "def":2, "ghi":3]; > > Error message is: > > prog.d:3: Error: non-constant expression ["abc":1,"def":2,"ghi":3] > > How is a literal non-constant? [...] Ugh. Just found this: http://d.puremagic.com/issues/show_bug.cgi?id=6238 Further testing shows that assoc array literals can't be used outside of function scope at all, for example: // (in package scope) auto hash = [ "abc":1, "def":2, "ghi":3 ]; // Error: non-constant expression ["abc":1,"def":2,"ghi":3] Seems like a pretty nasty bug to me. T -- If the comments and the code disagree, it's likely that *both* are wrong. -- Christopher |
February 04, 2012 Re: Associative array literal is non-constant? | ||||
---|---|---|---|---|
| ||||
On 02/04/12 07:46, H. S. Teoh wrote:
> On Fri, Feb 03, 2012 at 10:18:18PM -0800, H. S. Teoh wrote:
>> Why does the following code give a compiler error?
>>
>> static int[string] table = ["abc":1, "def":2, "ghi":3];
>>
>> Error message is:
>>
>> prog.d:3: Error: non-constant expression ["abc":1,"def":2,"ghi":3]
>>
>> How is a literal non-constant?
> [...]
>
> Ugh. Just found this:
>
> http://d.puremagic.com/issues/show_bug.cgi?id=6238
>
> Further testing shows that assoc array literals can't be used outside of function scope at all, for example:
>
> // (in package scope)
> auto hash = [ "abc":1, "def":2, "ghi":3 ];
> // Error: non-constant expression ["abc":1,"def":2,"ghi":3]
>
> Seems like a pretty nasty bug to me.
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. 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.
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.
Note: AA literals are documented to be non-const [1], so all of the above would be backwards compatible - it only allows for things which currently are illegal.
artur
[1] Somewhere on dlang.org. Can't find that page right now.
|
February 06, 2012 Re: Associative array literal is non-constant? | ||||
---|---|---|---|---|
| ||||
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. |
February 06, 2012 Re: Associative array literal is non-constant? | ||||
---|---|---|---|---|
| ||||
On Mon, Feb 06, 2012 at 11:46:00AM -0800, H. S. Teoh wrote: [...] > 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]. Hmm, I just checked TDPL again, and it seems that precedence has already been set for typeof(X) to be non-const. Which is OK, I guess, since with the current implementation we have: auto A = [1,2,3]; // int[] const B = [1,2,3]; // const(const(int)[]) -- why does // writeln(typeid(B)) give this funny // expression? auto X = ["a":1, "b":2]; // int[immutable(char)[]] const Y = ["a":1, "b":2]; // const(const(int)[immutable(char)[]]) (Of course, Y is currently still constructed on the heap.) Alternatively, if we don't want to risk breaking backward compatibility, maybe the new AA type should be "static T[U]" instead? I.e., introduce a new type called "static AA" which has a different implementation that is be computed at compile-time, and which is not compatible with the current AA's except via a .dup method that creates a heap-based AA. (Or should it be "immutable AA"?) T -- The best compiler is between your ears. -- Michael Abrash |
February 06, 2012 Re: Associative array literal is non-constant? | ||||
---|---|---|---|---|
| ||||
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
|
February 06, 2012 Re: Associative array literal is non-constant? | ||||
---|---|---|---|---|
| ||||
On 02/06/12 21:22, H. S. Teoh wrote:
> On Mon, Feb 06, 2012 at 11:46:00AM -0800, H. S. Teoh wrote: [...]
>> 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].
>
> Hmm, I just checked TDPL again, and it seems that precedence has already been set for typeof(X) to be non-const.
>
> Which is OK, I guess, since with the current implementation we have:
>
> auto A = [1,2,3]; // int[]
> const B = [1,2,3]; // const(const(int)[]) -- why does
> // writeln(typeid(B)) give this funny
> // expression?
>
> auto X = ["a":1, "b":2]; // int[immutable(char)[]]
> const Y = ["a":1, "b":2]; // const(const(int)[immutable(char)[]])
>
> (Of course, Y is currently still constructed on the heap.)
>
> Alternatively, if we don't want to risk breaking backward compatibility, maybe the new AA type should be "static T[U]" instead? I.e., introduce a new type called "static AA" which has a different implementation that is be computed at compile-time, and which is not compatible with the current AA's except via a .dup method that creates a heap-based AA.
>
> (Or should it be "immutable AA"?)
"static AA" is still mutable. "immutable" or "const" are not (you cannot modify an AA declared as const w/o casting away the constness).
artur
|
January 17, 2014 Re: Associative array literal is non-constant? | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Saturday, 4 February 2012 at 06:45:08 UTC, H. S. Teoh wrote:
> On Fri, Feb 03, 2012 at 10:18:18PM -0800, H. S. Teoh wrote:
>> Why does the following code give a compiler error?
>>
>> static int[string] table = ["abc":1, "def":2, "ghi":3];
>>
>> Error message is:
>>
>> prog.d:3: Error: non-constant expression ["abc":1,"def":2,"ghi":3]
>>
>> How is a literal non-constant?
> [...]
>
> Ugh. Just found this:
>
> http://d.puremagic.com/issues/show_bug.cgi?id=6238
>
> Further testing shows that assoc array literals can't be used outside of
> function scope at all, for example:
>
> // (in package scope)
> auto hash = [ "abc":1, "def":2, "ghi":3 ];
> // Error: non-constant expression ["abc":1,"def":2,"ghi":3]
>
> Seems like a pretty nasty bug to me.
>
>
> T
I would just like to add a vote for using assoc array literals outside of function scope. They are a handy way to represent data, and often data needs to be defined in other scopes.
|
Copyright © 1999-2021 by the D Language Foundation