www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Private enum members

reply Justin Johansson <no spam.com> writes:
My google search for

private "enum member" site:digitalmars.com

come up with nothing much so presumably this hasn't been discussed before.

There may be a valid use-case for being allowed to selectively mark
some enum members as being private, such as

enum Color {
  private UNINITIALIZED = -1,
  RED, GREEN, BLUE
}

(The above doesn't work in D1.  Haven't tried D2 though.)

(btw. Interestingly, typing this code into Eclipse with the Descent plug-in
causes a Java out of heap space malfunction.)

Is this a valid use-case?  What do you think?

-- Justin Johansson
Oct 23 2009
parent reply Justin Johansson <no spam.com> writes:
Sorry; subject line mod'ed  just so Ary doesn't miss it.

 enum Color { private UNINITIALIZED = -1, RED, GREEN, BLUE }

 (btw. Interestingly, typing this code into Eclipse with the Descent plug-in
 causes a Java out of heap space malfunction.)

Oct 23 2009
next sibling parent reply Yigal Chripun <yigal100 gmail.com> writes:
On 24/10/2009 01:16, Justin Johansson wrote:
 Sorry; subject line mod'ed  just so Ary doesn't miss it.

 enum Color { private UNINITIALIZED = -1, RED, GREEN, BLUE }

 (btw. Interestingly, typing this code into Eclipse with the Descent plug-in
 causes a Java out of heap space malfunction.)


enum Color { RED, GREEN, BLUE } void foo(Color* c) { if (c !is null) handleColor(*c); } what's the need for that UNINITIIALIZED member?
Oct 24 2009
parent reply Justin Johansson <no spam.com> writes:
Yigal Chripun Wrote:

 On 24/10/2009 01:16, Justin Johansson wrote:
 Sorry; subject line mod'ed  just so Ary doesn't miss it.

 enum Color { private UNINITIALIZED = -1, RED, GREEN, BLUE }

 (btw. Interestingly, typing this code into Eclipse with the Descent plug-in
 causes a Java out of heap space malfunction.)


enum Color { RED, GREEN, BLUE } void foo(Color* c) { if (c !is null) handleColor(*c); } what's the need for that UNINITIIALIZED member?

Okay; that's one work around for a corner case of my cited use-case, but you don't always want to, or perhaps it is not convenient/elegant to, use a pointer to data that conveniently fits into a machine register. Perhaps I am wrong but I thought uninit was a good metaphor to demonstrate the various useful purposes that private enum members might have. Here is another example that might make the concept jell. Again I may well be wrong. Consider this hypothetical enum definition together with plausible comments: enum Color { RED, GREEN, BLUE, // these 3 members are available for public consumption private RED_WITH_BLUE_POKER_DOTS, // this value is used internally and is not for public consumption and that's why it is marked private private RED_OR_GREEN, // ditto; internal routine to cater for red-green color-blindness } The above demonstrates a set of entities that are meaningful to some possible internal function but otherwise not externally meaningful. Another use-case lies in the API programmer's want for "private" .. so, for example, consider that "private" may well be a synonym for "pleasedontusethismemberbecauseitisalikelycandidateforfuturedeprecation" ** ** Using Walter Bright insignificant whitespace/separator notation :-) Thanks Yigal for commenting and perhaps your further comment? Justin
Oct 24 2009
next sibling parent Justin Johansson <no spam.com> writes:
Denis Koroskin Wrote:

 On Sat, 24 Oct 2009 19:00:10 +0400, Justin Johansson <no spam.com> wrote:
 
 Yigal Chripun Wrote:

 On 24/10/2009 01:16, Justin Johansson wrote:
 Sorry; subject line mod'ed  just so Ary doesn't miss it.

 enum Color { private UNINITIALIZED = -1, RED, GREEN, BLUE }

 (btw. Interestingly, typing this code into Eclipse with the Descent  


 causes a Java out of heap space malfunction.)


enum Color { RED, GREEN, BLUE } void foo(Color* c) { if (c !is null) handleColor(*c); } what's the need for that UNINITIIALIZED member?

Okay; that's one work around for a corner case of my cited use-case, but you don't always want to, or perhaps it is not convenient/elegant to, use a pointer to data that conveniently fits into a machine register. Perhaps I am wrong but I thought uninit was a good metaphor to demonstrate the various useful purposes that private enum members might have. Here is another example that might make the concept jell. Again I may well be wrong. Consider this hypothetical enum definition together with plausible comments: enum Color { RED, GREEN, BLUE, // these 3 members are available for public consumption private RED_WITH_BLUE_POKER_DOTS, // this value is used internally and is not for public consumption and that's why it is marked private private RED_OR_GREEN, // ditto; internal routine to cater for red-green color-blindness } The above demonstrates a set of entities that are meaningful to some possible internal function but otherwise not externally meaningful. Another use-case lies in the API programmer's want for "private" .. so, for example, consider that "private" may well be a synonym for "pleasedontusethismemberbecauseitisalikelycandidateforfuturedeprecation" ** ** Using Walter Bright insignificant whitespace/separator notation :-) Thanks Yigal for commenting and perhaps your further comment? Justin

Another useful use-case I see is enforcing explicit initialization: enum Color { private Uninitialized = 0, Red, Green, Blue, } Color color; // error: Color.Uninitialized is not accessible It would work similar to private struct ctors.

Absolutely! In general, I cannot see any reason why protection modifiers should not allowable for enums members in the same manner as for members of structs, classes, et. al.
Oct 24 2009
prev sibling parent reply Yigal Chripun <yigal100 gmail.com> writes:
On 24/10/2009 17:10, Denis Koroskin wrote:
 On Sat, 24 Oct 2009 19:00:10 +0400, Justin Johansson <no spam.com> wrote:

 Yigal Chripun Wrote:

 On 24/10/2009 01:16, Justin Johansson wrote:
 Sorry; subject line mod'ed just so Ary doesn't miss it.

 enum Color { private UNINITIALIZED = -1, RED, GREEN, BLUE }

 (btw. Interestingly, typing this code into Eclipse with the


 causes a Java out of heap space malfunction.)


enum Color { RED, GREEN, BLUE } void foo(Color* c) { if (c !is null) handleColor(*c); } what's the need for that UNINITIIALIZED member?

Okay; that's one work around for a corner case of my cited use-case, but you don't always want to, or perhaps it is not convenient/elegant to, use a pointer to data that conveniently fits into a machine register. Perhaps I am wrong but I thought uninit was a good metaphor to demonstrate the various useful purposes that private enum members might have. Here is another example that might make the concept jell. Again I may well be wrong. Consider this hypothetical enum definition together with plausible comments: enum Color { RED, GREEN, BLUE, // these 3 members are available for public consumption private RED_WITH_BLUE_POKER_DOTS, // this value is used internally and is not for public consumption and that's why it is marked private private RED_OR_GREEN, // ditto; internal routine to cater for red-green color-blindness } The above demonstrates a set of entities that are meaningful to some possible internal function but otherwise not externally meaningful. Another use-case lies in the API programmer's want for "private" .. so, for example, consider that "private" may well be a synonym for "pleasedontusethismemberbecauseitisalikelycandidateforfuturedeprecation" ** ** Using Walter Bright insignificant whitespace/separator notation :-) Thanks Yigal for commenting and perhaps your further comment? Justin

Another useful use-case I see is enforcing explicit initialization: enum Color { private Uninitialized = 0, Red, Green, Blue, } Color color; // error: Color.Uninitialized is not accessible It would work similar to private struct ctors.

I'd prefer D to have support for: enum Color { Red, Green, Blue } Color color; // compile time error Color? color; // OK I don't understand why would you want to hide certain enum values. In the colors example above, what's the rational behind hiding the RED_OR_GREEN value? personally I'd like to see D enums replaced by Java style enums which make more sense to me. D enums are even worse than C enums since you can write: enum foo = "text"; which to me looks very similar to: auto cat = new Dog;
Oct 24 2009
next sibling parent reply Justin Johansson <no spam.com> writes:
Yigal Chripun Wrote:

 On 24/10/2009 17:10, Denis Koroskin wrote:
 On Sat, 24 Oct 2009 19:00:10 +0400, Justin Johansson <no spam.com> wrote:

 Yigal Chripun Wrote:

 On 24/10/2009 01:16, Justin Johansson wrote:
 Sorry; subject line mod'ed just so Ary doesn't miss it.

 enum Color { private UNINITIALIZED = -1, RED, GREEN, BLUE }

 (btw. Interestingly, typing this code into Eclipse with the


 causes a Java out of heap space malfunction.)


enum Color { RED, GREEN, BLUE } void foo(Color* c) { if (c !is null) handleColor(*c); } what's the need for that UNINITIIALIZED member?

Okay; that's one work around for a corner case of my cited use-case, but you don't always want to, or perhaps it is not convenient/elegant to, use a pointer to data that conveniently fits into a machine register. Perhaps I am wrong but I thought uninit was a good metaphor to demonstrate the various useful purposes that private enum members might have. Here is another example that might make the concept jell. Again I may well be wrong. Consider this hypothetical enum definition together with plausible comments: enum Color { RED, GREEN, BLUE, // these 3 members are available for public consumption private RED_WITH_BLUE_POKER_DOTS, // this value is used internally and is not for public consumption and that's why it is marked private private RED_OR_GREEN, // ditto; internal routine to cater for red-green color-blindness } The above demonstrates a set of entities that are meaningful to some possible internal function but otherwise not externally meaningful. Another use-case lies in the API programmer's want for "private" .. so, for example, consider that "private" may well be a synonym for "pleasedontusethismemberbecauseitisalikelycandidateforfuturedeprecation" ** ** Using Walter Bright insignificant whitespace/separator notation :-) Thanks Yigal for commenting and perhaps your further comment? Justin

Another useful use-case I see is enforcing explicit initialization: enum Color { private Uninitialized = 0, Red, Green, Blue, } Color color; // error: Color.Uninitialized is not accessible It would work similar to private struct ctors.

I'd prefer D to have support for: enum Color { Red, Green, Blue } Color color; // compile time error Color? color; // OK

 I don't understand why would you want to hide certain enum values. In 
 the colors example above, what's the rational behind hiding the 
 RED_OR_GREEN value?

Let me try again. You have a set of N things which are represented by an enum definition. There is some subset of this set containing M things (so M < N) which represents the things meaningful in a public sense. The remaining Q=N-M members of the whole set are only meaningful to some internal processing so this subset containing Q members are designated private. I'm trying to think about this problem in an abstract way; sometimes giving concrete examples like Color colors (pun intended) the abstract problem. Maybe there is no good physical example and therefore I am wrong.
 personally I'd like to see D enums replaced by Java style enums which 
 make more sense to me. D enums are even worse than C enums since you can 
 write:
 enum foo = "text";
 
 which to me looks very similar to:
 auto cat = new Dog;

I didn't know this one. It does sound like the design of D enums needs revisiting. Perhaps others will chime in on this?
Oct 24 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-10-24 18:45:10 -0400, Justin Johansson <no spam.com> said:

 Let me try again.  You have a set of N things which are represented by
 an enum definition.  There is some subset of this set containing M
 things (so M < N) which represents the things meaningful in a public
 sense.  The remaining Q=N-M members of the whole set are only meaningful
 to some internal processing so this subset containing Q members are
 designated private.  I'm trying to think about this problem in an abstract
 way; sometimes giving concrete examples like Color colors (pun intended)
 the abstract problem.

Sounds like you want enum inheritance: one enum being a superset of another. :-) -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 24 2009
next sibling parent Rainer Deyke <rainerd eldwood.com> writes:
Denis Koroskin wrote:
 On Sun, 25 Oct 2009 02:22:51 +0300, Michel Fortin
 <michel.fortin michelf.com> wrote:
 Sounds like you want enum inheritance: one enum being a superset of
 another.  :-)


I was about to post the same thing.
 It was previously proposed, but it was rejected because it works
 "backwards": downcasting is allowed while upcasting is prohibited.

Just like contravariant functions. Only less so. -- Rainer Deyke - rainerd eldwood.com
Oct 24 2009
prev sibling parent Yigal Chripun <yigal100 gmail.com> writes:
On 25/10/2009 01:22, Michel Fortin wrote:
 On 2009-10-24 18:45:10 -0400, Justin Johansson <no spam.com> said:

 Let me try again. You have a set of N things which are represented by
 an enum definition. There is some subset of this set containing M
 things (so M < N) which represents the things meaningful in a public
 sense. The remaining Q=N-M members of the whole set are only meaningful
 to some internal processing so this subset containing Q members are
 designated private. I'm trying to think about this problem in an abstract
 way; sometimes giving concrete examples like Color colors (pun intended)
 the abstract problem.

Sounds like you want enum inheritance: one enum being a superset of another. :-)

I think the simplest way to do what you want is to have two enums, maybe one with the public members and one with the private ones. another option, a private enum with all the values and a public one with just the public ones.
Oct 24 2009
prev sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Yigal Chripun wrote:
 personally I'd like to see D enums replaced by Java style enums which 
 make more sense to me. D enums are even worse than C enums since you can 
 write:
 enum foo = "text";
 
 which to me looks very similar to:
 auto cat = new Dog;

I agree that enum is a horrible keyword to use for declaring manifest constants. In my opinion the D developers are sometimes a bit too afraid of introducing new keywords, and this is one of the consequences. Personally, I think this would be a better scheme: const: manifest constants, no storage (like const in D1, enum in D2) readonly: used for a read-only view of mutable data (like const in D2) immutable: truly immutable data (like now) -Lars
Oct 26 2009
parent reply Yigal Chripun <yigal100 gmail.com> writes:
On 26/10/2009 12:07, Lars T. Kyllingstad wrote:
 Yigal Chripun wrote:
 personally I'd like to see D enums replaced by Java style enums which
 make more sense to me. D enums are even worse than C enums since you
 can write:
 enum foo = "text";

 which to me looks very similar to:
 auto cat = new Dog;

I agree that enum is a horrible keyword to use for declaring manifest constants. In my opinion the D developers are sometimes a bit too afraid of introducing new keywords, and this is one of the consequences. Personally, I think this would be a better scheme: const: manifest constants, no storage (like const in D1, enum in D2) readonly: used for a read-only view of mutable data (like const in D2) immutable: truly immutable data (like now) -Lars

i don't think we need to add more options, I think we need to remove options. there should be only two types, const and mutable. manifest constants should be a linker optimization and immutable is only relevant as part of a concurrency model and even then there's no need for a separate keyword. immutable objects are shared objects where only the owner is allowed to modify it and only if it's done in a thread-safe way (synchronized with locks, lock-free algorithms). void foo() { // can be optimized away (transformed into a manifest constant) // taking address of var is illegal const var = 42; // allocated on the heap and you can pass it's address around auto bar = new const int(42); }
Oct 26 2009
parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Yigal Chripun wrote:
 On 26/10/2009 12:07, Lars T. Kyllingstad wrote:
 Yigal Chripun wrote:
 personally I'd like to see D enums replaced by Java style enums which
 make more sense to me. D enums are even worse than C enums since you
 can write:
 enum foo = "text";

 which to me looks very similar to:
 auto cat = new Dog;

I agree that enum is a horrible keyword to use for declaring manifest constants. In my opinion the D developers are sometimes a bit too afraid of introducing new keywords, and this is one of the consequences. Personally, I think this would be a better scheme: const: manifest constants, no storage (like const in D1, enum in D2) readonly: used for a read-only view of mutable data (like const in D2) immutable: truly immutable data (like now) -Lars

i don't think we need to add more options, I think we need to remove options. there should be only two types, const and mutable. manifest constants should be a linker optimization and immutable is only relevant as part of a concurrency model and even then there's no need for a separate keyword. immutable objects are shared objects where only the owner is allowed to modify it and only if it's done in a thread-safe way (synchronized with locks, lock-free algorithms). void foo() { // can be optimized away (transformed into a manifest constant) // taking address of var is illegal const var = 42; // allocated on the heap and you can pass it's address around auto bar = new const int(42); }

I was going to protest: "But what about const struct members? Should the size of the following struct depend on whether the compiler determines it can optimize by turning its const member into a manifest constant?" struct Foo { const int bar = 123; } But then I decided to actually try it with the current DMD2, and found that the compiler does just that! writeln(Foo.sizeof); // Prints "1", not "4" Foo foo; auto p = &foo.bar; // Error: constant 123 is not an lvalue What's going on? Is this intended behaviour? -Lars
Oct 27 2009
parent reply Yigal Chripun <yigal100 gmail.com> writes:
Lars T. Kyllingstad Wrote:

 
 I was going to protest: "But what about const struct members? Should the 
 size of the following struct depend on whether the compiler determines 
 it can optimize by turning its const member into a manifest constant?"
 
    struct Foo { const int bar = 123; }
 
 But then I decided to actually try it with the current DMD2, and found 
 that the compiler does just that!
 
    writeln(Foo.sizeof);    // Prints "1", not "4"
 
    Foo foo;
    auto p = &foo.bar;   // Error: constant 123 is not an lvalue
 
 What's going on? Is this intended behaviour?
 
 -Lars

what D version? in D1 const is a manifest constant as far as I know. to answer to general question, "what about structs": I'd say that the same rules should apply just like inside functions. struct Foo { const int num = 42; } // num should be a manifest const can you give a use-case/example where you wouldn't want to do that but rather store the constant in the struct?
Oct 27 2009
parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Yigal Chripun wrote:
 Lars T. Kyllingstad Wrote:
 
 I was going to protest: "But what about const struct members? Should the 
 size of the following struct depend on whether the compiler determines 
 it can optimize by turning its const member into a manifest constant?"

    struct Foo { const int bar = 123; }

 But then I decided to actually try it with the current DMD2, and found 
 that the compiler does just that!

    writeln(Foo.sizeof);    // Prints "1", not "4"

    Foo foo;
    auto p = &foo.bar;   // Error: constant 123 is not an lvalue

 What's going on? Is this intended behaviour?

 -Lars

what D version?

DMD 2.035.
 in D1 const is a manifest constant as far as I know. 

Yes, but in D2 the spec says that const is a constant view of mutable data. There isn't (or at least I can't find) mention that struct members are excepted from this rule.
 to answer to general question, "what about structs": 
 I'd say that the same rules should apply just like inside functions. 
 
 struct Foo { const int num = 42; } // num should be a manifest const
 
 can you give a use-case/example where you wouldn't want to do that but rather
store the constant in the struct? 

In any case where a different view of the same data is non-const. Or would you also disallow casting away const-ness? -Lars
Oct 27 2009
prev sibling next sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
Justin Johansson wrote:
 Sorry; subject line mod'ed  just so Ary doesn't miss it.
 
 enum Color { private UNINITIALIZED = -1, RED, GREEN, BLUE }

 (btw. Interestingly, typing this code into Eclipse with the Descent plug-in
 causes a Java out of heap space malfunction.)


Thanks, fixed!
Oct 24 2009
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Sat, 24 Oct 2009 19:00:10 +0400, Justin Johansson <no spam.com> wrote:

 Yigal Chripun Wrote:

 On 24/10/2009 01:16, Justin Johansson wrote:
 Sorry; subject line mod'ed  just so Ary doesn't miss it.

 enum Color { private UNINITIALIZED = -1, RED, GREEN, BLUE }

 (btw. Interestingly, typing this code into Eclipse with the Descent  


 causes a Java out of heap space malfunction.)


enum Color { RED, GREEN, BLUE } void foo(Color* c) { if (c !is null) handleColor(*c); } what's the need for that UNINITIIALIZED member?

Okay; that's one work around for a corner case of my cited use-case, but you don't always want to, or perhaps it is not convenient/elegant to, use a pointer to data that conveniently fits into a machine register. Perhaps I am wrong but I thought uninit was a good metaphor to demonstrate the various useful purposes that private enum members might have. Here is another example that might make the concept jell. Again I may well be wrong. Consider this hypothetical enum definition together with plausible comments: enum Color { RED, GREEN, BLUE, // these 3 members are available for public consumption private RED_WITH_BLUE_POKER_DOTS, // this value is used internally and is not for public consumption and that's why it is marked private private RED_OR_GREEN, // ditto; internal routine to cater for red-green color-blindness } The above demonstrates a set of entities that are meaningful to some possible internal function but otherwise not externally meaningful. Another use-case lies in the API programmer's want for "private" .. so, for example, consider that "private" may well be a synonym for "pleasedontusethismemberbecauseitisalikelycandidateforfuturedeprecation" ** ** Using Walter Bright insignificant whitespace/separator notation :-) Thanks Yigal for commenting and perhaps your further comment? Justin

Another useful use-case I see is enforcing explicit initialization: enum Color { private Uninitialized = 0, Red, Green, Blue, } Color color; // error: Color.Uninitialized is not accessible It would work similar to private struct ctors.
Oct 24 2009
prev sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 25 Oct 2009 02:22:51 +0300, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2009-10-24 18:45:10 -0400, Justin Johansson <no spam.com> said:

 Let me try again.  You have a set of N things which are represented by
 an enum definition.  There is some subset of this set containing M
 things (so M < N) which represents the things meaningful in a public
 sense.  The remaining Q=N-M members of the whole set are only meaningful
 to some internal processing so this subset containing Q members are
 designated private.  I'm trying to think about this problem in an  
 abstract
 way; sometimes giving concrete examples like Color colors (pun intended)
 the abstract problem.

Sounds like you want enum inheritance: one enum being a superset of another. :-)

It was previously proposed, but it was rejected because it works "backwards": downcasting is allowed while upcasting is prohibited. Consider the following example (taken from DMD): enum Token { colon, semicolon, eof, // ... max, } enum AsmToken : Token // "extend" an existing enum { dword, // = Token.max + 1 implicitly even, far, naked, near, ptr, qword, seg, word, } Now this is very useful, and less error prone than manual enum values management. Less jump to the usage: AsmToken tok1 = Token.colon; // fine Token tok2 = AsmToken.dword; // error The two lines above are exact opposite of class/interface inheritance behavior: class Token {} class AsmToken : Token {} AsmToken tok1 = new Token(); // error Token tok2 = new AsmToken(); // fine which makes sense but confusing for novices. IIRC, Walter rejected the feature for exactly this reason.
Oct 24 2009