Mutable enums

Timon Gehr timon.gehr at gmx.ch
Wed Nov 16 11:26:57 PST 2011


On 11/16/2011 02:22 PM, Steven Schveighoffer wrote:
> On Tue, 15 Nov 2011 13:45:02 -0500, Timon Gehr <timon.gehr at gmx.ch> wrote:
>
>> On 11/15/2011 04:53 PM, Steven Schveighoffer wrote:
>
>>> Yes, but this is spelled out because copying a static array requires
>>> moving data. However, this does *not* require a hidden allocation (even
>>> though it does do a hidden allocation currently).
>>>
>>> I'm not worried about copying data as much as I am about hidden
>>> allocations. Hidden allocations are a huge drag on performance. Every
>>> time you allocate, you need to take a global GC lock, and it's an
>>> unbounded operation (doing one allocation could run a collection cycle).
>>
>> You don't actually _need_ a global GC lock. It is just how it is
>> implemented in this case.
>
> This is all fine in theory. I haven't seen any implementations. But
> memory allocations are not cheap, even without a GC lock.
>
>> Note that this is an explicit allocation:
>>
>> int[] a = [1,2,3]; // just as explicit as a NewExpression
>>
>> Only the enums "hide" it sometimes, but actually you should know the
>> involved types.
>
> As I've said, there are already ways to explicitly allocate memory. A
> suggested replacement for this is:
>
> int[] a = array(1, 2, 3);
>
> And you could always do:
>
> int[] a = [1, 2, 3].dup;
>
> Nobody complains about having to do:
>
> char[] a = "hello".dup;
>
> I don't see why we couldn't do the same for all array literals.
>

Because 'immutable' behaves nicely on built-in value types, but not on 
arbitrary reference types.


>>> That is the idea. Get rid of the hidden allocation. Writeln *is* const
>>> correct, it can certainly print immutable(int)[].
>>
>> Well, there is a function called writeln that can do that. That is a
>> different function. But the one that gets actually called is not const
>> correct as well.
>>
>>
>> This is writeln:
>>
>> // Most general instance
>> void writeln(T...)(T args)
>> if (T.length > 1 || T.length == 1 && !is(typeof(args[0]) :
>> const(char)[]))
>> {
>> stdout.write(args, '\n');
>> }
>>
>>
>> =>
>> writeln([1,2,3]);
>> // modulo IFTY:
>> writeln!(int[])([1,2,3]);
>> // const correct?
>> writeln!(int[])([1,2,3].idup); // nope!
>>
>> Error: cannot implicitly convert expression (_adDupT(&
>> _D11TypeInfo_Ai6__initZ,[1,2,3])) of type immutable(int)[] to int[]
>
> I'm not sure what this means. If [1, 2, 3] is typed as immtuable(int)[],
> it will compile.
>
> Simple test:
>
> immutable(int)[] a = [1, 2, 3];
> writeln(a);
>
> works with 2.056.

That is like saying

void foo(int[] a){...}             // prints a
void bar(immutable(int)[] a){...}  // prints a

int[] a = [1,2,3];
immutable(int)[] b = [1, 2, 3];
foo(a);
bar(b);

"=> Oh, bar is const correct because I can call foo with mutable data 
and bar with immutable data."

foo is writeln!(int[])
bar is writeln!(immutable(int)[])

in effect, if you do:

writeln("hello".dup);

The compiler cannot assume that the IFTI'd writeln!(char[]) will not 
change the argument, ergo it cannot optimize away the .dup, even though 
it would be a valid transformation as long as the programmer does not 
make the program semantics depend on the identity relation on immutable 
references (doing so defeats the purpose of immutability).


>
>>> The issue is not
>>> writeln, it's what the type of the array literal/enum is.
>>>
>>
>>> Technically, an array literal is equivalent to an enum, and should
>>> follow the same rules.
>>>
>>
>> Remember that immutable is transitive. That can really get in your way
>> in this case.
>
> If the data is stored in ROM, it should be typed as immutable. If it's
> not, then it could be modified. The only other option is heap allocation
> and construction on use, which I've already said is undesirable.
>
> If we start from "all array literals and enums that contain references
> store the referenced data in ROM," then we will find ways to deal with
> any inconveniences. It's all a matter of what's more important in a
> system language, performance or convenience.

Both are more important. It is D.
Everything you need to do is make the enum static immutable instead.
D is also a scripting language and an application programming language.

auto a = [new Foo, new Bar, new Qux]; // I want that to work.








More information about the Digitalmars-d-learn mailing list