Mutable enums

Timon Gehr timon.gehr at gmx.ch
Wed Nov 16 14:39:16 PST 2011


On 11/16/2011 10:56 PM, Steven Schveighoffer wrote:
> On Wed, 16 Nov 2011 16:16:48 -0500, Timon Gehr <timon.gehr at gmx.ch> wrote:
>
>> On 11/16/2011 09:00 PM, Steven Schveighoffer wrote:
>>> On Wed, 16 Nov 2011 14:26:57 -0500, Timon Gehr <timon.gehr at gmx.ch>
>>> wrote:
>>>
>>>> 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:
>>>>>
>>>>>> 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.
>>>
>>> string is a reference type. We hear no complaints about strings being
>>> stored in ROM and the type of literals being immutable.
>>>
>>
>> string is not an immutable type. It is immutable(char)[] and char is a
>> built-in value type.
>>
>> static assert(isMutable!string);
>
> It fits my definition of a valid enum reference type (immutable or
> implicitly castable to immutable). The point is that the data referenced
> is stored in ROM and therefore a) immutable and b) fully defined at
> compile-time.

Indeed. But fact is, the data that is qualified with immutable is not of 
reference type therefore it behaves nicely. And you don't get that in 
the general case.

>
>>> Make no mistake, this doesn't cover every current instance array
>>> literals, such as ones which contain necessarily-heap-allocated
>>> entities. Those would be covered by a library function (e.g.
>>> array(...)). But those are not array literals anyways, they are
>>> constructors.
>>>
>>
>> It is true that they are constructors, but they are currently also
>> called array literals.
>
> I'm looking to redefine what a literal means in D.
>
>>>
>>> writeln is not contractually const correct, but that's only because most
>>> of D is not const correct either. For example, Object.toString is not
>>> const, so if you const-ified all writeln args, you couldn't print
>>> objects. But writeln itself does not change any data (a rogue toString
>>> might change data, but that is not common practice).
>>>
>>> Once D becomes const correct, writeln *can* apply const to all it's
>>> parameters.
>>
>> Ok, I see. writeln still could be const-correct in principle. It would
>> need to apply const to the parameters that have a const toString
>> method. But the language is not powerful enough to do that. There is
>> no way to intercept IFTI... I am commonly missing that feature.
>

I am looking for something like this:

template writeln(T...)(T){
     alias writelnImpl!(writelnInferConst!T) writeln;
}

(it is even trivial to parse, unlike normal function definitions!)

> I have an enhancement request in for intercepting IFTI (not sure if it
> applies here): http://d.puremagic.com/issues/show_bug.cgi?id=4998
>

It has a complexity of at least 2^numparams and probably all kinds of 
odd implications for the compiler internals that would lead to a buggy 
implementation.

I think this is a better solution:

void foo2(T: ParameterTypeTuple!foo[0])(T t){foo(t);}

Then it is just a matter of applying proper value range propagation for 
IFTY:

void bar(T: short)(T t){...}

void main(){
     bar(1); // ok
}



>>>
>>>>> 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.
>>>
>>> auto a = array(new Foo, new Bar, new Qux);
>>>
>>
>> Requiring that works modulo template bloat and breakage of existing
>> code. Also, it does not really buy us anything imho.
>
> I think the bloat is a wash. Every time I use an array literal, there is
> a complete instantiation of what would be in an array template inline in
> the calling function.

With the template function you have that too because the calling 
function builds the arguments. It is just that you also get the template 
bloat and an additional function call. Unless it is inlined, of course.

>
> Yes, it breaks code. It's worth it. To avoid a heap allocation for [1,
> 2, 3] is worth breaking code that uses runtime data in an array literal.
> The compiler can be helpful in the error message:
>
> Error somefile.d(345): array literals cannot contain runtime data. Maybe
> you meant:
> array(new Foo, new Bar, new Qux);
>
> I want to point out that currently there is *NO* way to make an
> immutable array literal that lives in ROM. This is unacceptable.
>

There is:

void main(){
     static immutable x = [1,2,3];
}


And the compiler *really* should write this to ROM:

void main(){
     immutable(int)[] x=[1,2,3]; // should be slice to ROM, because the 
array literal contents are typed as immutable and known during compile time.
}











More information about the Digitalmars-d-learn mailing list