Jump to page: 1 24  
Page
Thread overview
Mutable enums
Nov 13, 2011
bearophile
Nov 13, 2011
Jonathan M Davis
Nov 14, 2011
bearophile
Nov 14, 2011
Jonathan M Davis
Nov 14, 2011
so
Nov 14, 2011
Jonathan M Davis
Nov 14, 2011
so
Nov 14, 2011
Jonathan M Davis
Nov 14, 2011
Timon Gehr
Nov 14, 2011
Timon Gehr
Nov 14, 2011
so
Nov 14, 2011
Timon Gehr
Nov 14, 2011
Dejan Lekic
Nov 14, 2011
Timon Gehr
Nov 14, 2011
Timon Gehr
Nov 14, 2011
Timon Gehr
Nov 15, 2011
Timon Gehr
Nov 16, 2011
Timon Gehr
Nov 16, 2011
Timon Gehr
Nov 16, 2011
Timon Gehr
Nov 16, 2011
Timon Gehr
Nov 16, 2011
Timon Gehr
Nov 17, 2011
Timon Gehr
Nov 17, 2011
Timon Gehr
Nov 16, 2011
Simen Kjærås
Nov 15, 2011
so
November 13, 2011
Do you remember if this bug is in Bugzilla?


import std.algorithm;
void main() {
    enum a = [3, 1, 2];
    enum s = sort(a);
    assert(equal(a, [3, 1, 2]));
    assert(equal(s, [1, 2, 3]));
}


Bye,
bearophile
November 13, 2011
On Sunday, November 13, 2011 17:54:14 bearophile wrote:
> Do you remember if this bug is in Bugzilla?
> 
> 
> import std.algorithm;
> void main() {
>     enum a = [3, 1, 2];
>     enum s = sort(a);
>     assert(equal(a, [3, 1, 2]));
>     assert(equal(s, [1, 2, 3]));
> }

It's not a bug. Those an manifest constants. They're copy-pasted into whatever code you used them in. So,

enum a = [3, 1, 2];
enum s = sort(a);

is equivalent to

enum a = [3, 1, 2];
enum s = sort([3, 1, 2]);

a isn't altered at all, because a doesn't really exist. Notice that

assert(equal(a, [3, 1, 2]));

still passes. It's equivalent to

assert(equal([3, 1, 2], [3, 1, 2]));

- Jonathan M Davis
November 14, 2011
Jonathan M Davis:

> > import std.algorithm;
> > void main() {
> >     enum a = [3, 1, 2];
> >     enum s = sort(a);
> >     assert(equal(a, [3, 1, 2]));
> >     assert(equal(s, [1, 2, 3]));
> > }
> 
> It's not a bug. Those an manifest constants. They're copy-pasted into whatever code you used them in. So,
> 
> enum a = [3, 1, 2];
> enum s = sort(a);
> 
> is equivalent to
> 
> enum a = [3, 1, 2];
> enum s = sort([3, 1, 2]);

You are right, there's no DMD bug here. Yet, it's a bit surprising to sort in-place a "constant". I have to stop thinking of them as constants. I don't like this design of enums...

On the other hand this gives the error message I was looking for, until today I didn't even think about const enums:

import std.algorithm;
const enum a = [1, 2];
void main() {
    sort(a);
}


So I guess I'll start using "cont enum" and "immutable enum" instead of enums :-)

Bye,
bearophile
November 14, 2011
On Sunday, November 13, 2011 19:02:01 bearophile wrote:
> Jonathan M Davis:
> > > import std.algorithm;
> > > void main() {
> > > 
> > >     enum a = [3, 1, 2];
> > >     enum s = sort(a);
> > >     assert(equal(a, [3, 1, 2]));
> > >     assert(equal(s, [1, 2, 3]));
> > > 
> > > }
> > 
> > It's not a bug. Those an manifest constants. They're copy-pasted into whatever code you used them in. So,
> > 
> > enum a = [3, 1, 2];
> > enum s = sort(a);
> > 
> > is equivalent to
> > 
> > enum a = [3, 1, 2];
> > enum s = sort([3, 1, 2]);
> 
> You are right, there's no DMD bug here. Yet, it's a bit surprising to sort in-place a "constant". I have to stop thinking of them as constants. I don't like this design of enums...
> 
> On the other hand this gives the error message I was looking for, until today I didn't even think about const enums:
> 
> import std.algorithm;
> const enum a = [1, 2];
> void main() {
>     sort(a);
> }
> 
> 
> So I guess I'll start using "cont enum" and "immutable enum" instead of enums :-)

It depends entirely on what you're trying to do. If you understand how manifest constants work, then they can be quite advantageous. What you probably really want for arrays though is not an enum but just a const or immutable module variable.

immutable a = [3, 1, 2];

Otherwise, you're allocating a new array every time you use the enum. So, use a manifest constant when you want to avoid having it take up any memory but don't care about whatever allocations may occur when it's used (primitive types such as ints being a prime example), whereas if you want an actual memory location for the constant and/or want it to be allocated only once, then use variable rather than an enum.

- Jonathan M Davis
November 14, 2011
On Mon, 14 Nov 2011 02:09:40 +0200, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> It depends entirely on what you're trying to do. If you understand how
> manifest constants work, then they can be quite advantageous. What you
> probably really want for arrays though is not an enum but just a const or
> immutable module variable.
>
> immutable a = [3, 1, 2];
>
> Otherwise, you're allocating a new array every time you use the enum. So, use
> a manifest constant when you want to avoid having it take up any memory but
> don't care about whatever allocations may occur when it's used (primitive
> types such as ints being a prime example), whereas if you want an actual
> memory location for the constant and/or want it to be allocated only once,
> then use variable rather than an enum.
>
> - Jonathan M Davis

Wait a second, it is definitely a bug. You can't modify an enum.

"immutable a = [3, 1, 2];" is practically "enum a = [3, 1, 2];".
November 14, 2011
On Monday, November 14, 2011 02:16:57 so wrote:
> On Mon, 14 Nov 2011 02:09:40 +0200, Jonathan M Davis <jmdavisProg@gmx.com>
> 
> wrote:
> > It depends entirely on what you're trying to do. If you understand how
> > manifest constants work, then they can be quite advantageous. What you
> > probably really want for arrays though is not an enum but just a const
> > or
> > immutable module variable.
> > 
> > immutable a = [3, 1, 2];
> > 
> > Otherwise, you're allocating a new array every time you use the enum.
> > So, use
> > a manifest constant when you want to avoid having it take up any memory
> > but
> > don't care about whatever allocations may occur when it's used
> > (primitive
> > types such as ints being a prime example), whereas if you want an actual
> > memory location for the constant and/or want it to be allocated only
> > once,
> > then use variable rather than an enum.
> > 
> > - Jonathan M Davis
> 
> Wait a second, it is definitely a bug. You can't modify an enum.
> 
> "immutable a = [3, 1, 2];" is practically "enum a = [3, 1, 2];".

No. Those are two _very_ different things.

immutable a = [3, 1, 2];

creates a variable of type immutable(int[]). You takes up memory. You can take its address - e.g. &a. It exists even if you don't use it at all.

enum a = [3, 1, 2];

on the other hand, doesn't create any variable at all. It's what's called a manifest constant. It's a placeholder. It takes up no memory. You can't take its address. If you never use it, it doesn't end up in the generated program at all. Every use of a effectively copies the value of a to wherever its used. So,

enum a = [3, 1, 2];
sort(a);

is _identical_ to

sort([3, 1, 2]);

That means that if you use a in any code, it's copied in that code such that you could end up allocating a lot of memory that you didn't intend to if you heavily use manifest constants which are strings or arrays. But it also means that you get a new copy to use at each location, which can also be useful. And for types that don't end up on the heap (e.g. int), there's really no cost to it, and it actually is _more_ efficient (albeit marginally), since it avoids having to allocate any memory for the enum itself, since it's not a variable.

- Jonathan M Davis
November 14, 2011
On Mon, 14 Nov 2011 02:50:50 +0200, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> No. Those are two _very_ different things.
>
> immutable a = [3, 1, 2];
>
> creates a variable of type immutable(int[]). You takes up memory. You can take
> its address - e.g. &a. It exists even if you don't use it at all.
>
> enum a = [3, 1, 2];
>
> on the other hand, doesn't create any variable at all. It's what's called a
> manifest constant. It's a placeholder. It takes up no memory. You can't take
> its address. If you never use it, it doesn't end up in the generated program
> at all. Every use of a effectively copies the value of a to wherever its used.
> So,
>
> enum a = [3, 1, 2];
> sort(a);
>
> is _identical_ to
>
> sort([3, 1, 2]);
>
> That means that if you use a in any code, it's copied in that code such that
> you could end up allocating a lot of memory that you didn't intend to if you
> heavily use manifest constants which are strings or arrays. But it also means
> that you get a new copy to use at each location, which can also be useful. And
> for types that don't end up on the heap (e.g. int), there's really no cost to
> it, and it actually is _more_ efficient (albeit marginally), since it avoids
> having to allocate any memory for the enum itself, since it's not a variable.
>
> - Jonathan M Davis

Trying to remember the discussions on digitalmars.D regarding enum/immutable. There were contradicting opinions.
You ask the same question at two different times, you get at least two different answers, especially on this matter.
There was/is not a consensus on how it works or should work.

While i think enum/immutable are not same thing. Because with enum you mean it is a compile time value and compile time only, but immutable might rely on runtime initializers. So it differs here. This just means enum gives you more guaranties, not less.

enum a = 5;
immutable b = 6;
a = 3;
b = 3;

If the above code is invalid for both enum and immutable, so should the "in-place" sort case. I understand how it works, but it doesn't make any sense why it should work that way.
November 14, 2011
On Monday, November 14, 2011 04:03:54 so wrote:
> Trying to remember the discussions on digitalmars.D regarding
> enum/immutable. There were contradicting opinions.
> You ask the same question at two different times, you get at least two
> different answers, especially on this matter.
> There was/is not a consensus on how it works or should work.
> 
> While i think enum/immutable are not same thing. Because with enum you mean it is a compile time value and compile time only, but immutable might rely on runtime initializers. So it differs here. This just means enum gives you more guaranties, not less.
> 
> enum a = 5;
> immutable b = 6;
> a = 3;
> b = 3;
> 
> If the above code is invalid for both enum and immutable, so should the "in-place" sort case. I understand how it works, but it doesn't make any sense why it should work that way.

It works exactly as it's designed to work. There are people who disagree with how it's designed, but it works exactly as designed. The above is invalid, because you can't assign to an enum - it's not a variable - and you can't assign to an immutable variable. sort works with an enum because you're passing it a valid array which is _not_ immutable. It's a new array just as if you'd passed it the enum's value directly. That may be surprising to some, but it's exactly as designed and is not a bug. If you think that it should work differently, then you're arguing against the current design, which is a completely different discussion.

- Jonathan M Davis
November 14, 2011
On 11/14/2011 01:02 AM, bearophile wrote:
> Jonathan M Davis:
>
>>> import std.algorithm;
>>> void main() {
>>>      enum a = [3, 1, 2];
>>>      enum s = sort(a);
>>>      assert(equal(a, [3, 1, 2]));
>>>      assert(equal(s, [1, 2, 3]));
>>> }
>>
>> It's not a bug. Those an manifest constants. They're copy-pasted into whatever
>> code you used them in. So,
>>
>> enum a = [3, 1, 2];
>> enum s = sort(a);
>>
>> is equivalent to
>>
>> enum a = [3, 1, 2];
>> enum s = sort([3, 1, 2]);
>
> You are right, there's no DMD bug here. Yet, it's a bit surprising to sort in-place a "constant". I have to stop thinking of them as constants. I don't like this design of enums...

It is the right design. Why should enum imply const or immutable? (or inout, for that matter). They are completely orthogonal.

enum Enum{
    opt1,
    opt2,
}

void main(){
    auto moo = Enum.opt1;
    moo = Enum.opt2; // who would seriously want an error here???
}


enum a = [1,2,3];

void main(){
    auto x = a;
    x = [2,1,3]; // ditto
}


>
> On the other hand this gives the error message I was looking for, until today I didn't even think about const enums:
>
> import std.algorithm;
> const enum a = [1, 2];
> void main() {
>      sort(a);
> }
>
>
> So I guess I'll start using "cont enum" and "immutable enum" instead of enums :-)
>

You can do that, but they are not a full replacement. How would you get a sorted version of such an enum, for instance? =)
November 14, 2011
On 11/14/2011 09:27 AM, Timon Gehr wrote:
> On 11/14/2011 01:02 AM, bearophile wrote:
>> Jonathan M Davis:
>>
>>>> import std.algorithm;
>>>> void main() {
>>>> enum a = [3, 1, 2];
>>>> enum s = sort(a);
>>>> assert(equal(a, [3, 1, 2]));
>>>> assert(equal(s, [1, 2, 3]));
>>>> }
>>>
>>> It's not a bug. Those an manifest constants. They're copy-pasted into
>>> whatever
>>> code you used them in. So,
>>>
>>> enum a = [3, 1, 2];
>>> enum s = sort(a);
>>>
>>> is equivalent to
>>>
>>> enum a = [3, 1, 2];
>>> enum s = sort([3, 1, 2]);
>>
>> You are right, there's no DMD bug here. Yet, it's a bit surprising to
>> sort in-place a "constant". I have to stop thinking of them as
>> constants. I don't like this design of enums...
>
> It is the right design. Why should enum imply const or immutable? (or
> inout, for that matter). They are completely orthogonal.
>
> enum Enum{
> opt1,
> opt2,
> }
>
> void main(){
> auto moo = Enum.opt1;
> moo = Enum.opt2; // who would seriously want an error here???
> }
>
>
> enum a = [1,2,3];
>
> void main(){
> auto x = a;
> x = [2,1,3]; // ditto
> }
>
>
>>
>> On the other hand this gives the error message I was looking for,
>> until today I didn't even think about const enums:
>>
>> import std.algorithm;
>> const enum a = [1, 2];
>> void main() {
>> sort(a);
>> }
>>
>>
>> So I guess I'll start using "cont enum" and "immutable enum" instead
>> of enums :-)
>>
>
> You can do that, but they are not a full replacement. How would you get
> a sorted version of such an enum, for instance? =)

(.dup, obviously.)
« First   ‹ Prev
1 2 3 4