digitalmars.D - Enums - probably an old subject
- Steve Teale (19/19) Nov 20 2013 import std.stdio;
- Craig Dillabaugh (4/23) Nov 20 2013 That should be:
- Craig Dillabaugh (8/17) Nov 20 2013 clip
- Michal Minich (25/27) Nov 21 2013 I don't entirely think so. I think the OP is arguing that D
- Craig Dillabaugh (5/16) Nov 21 2013 Yes, perhaps that was his intention (no pun intended). First few
- Steve Teale (3/6) Nov 21 2013 Pun was intended ;=)
- Steve Teale (16/44) Nov 21 2013 Michal,
- Andrei Alexandrescu (4/7) Nov 21 2013 Guess it could. One other thing we could do is to make enum namespaces
- Brad Anderson (3/12) Nov 21 2013 +1. I love this idea. Verbosity only when necessary.
- Steve Teale (4/13) Nov 21 2013 I'd love to understand "make enum namespaces behave like
- monarch_dodra (38/53) Nov 21 2013 When you import from a module, you only need to specify the
- John J (7/43) Nov 21 2013 If both these enums are coming from a module and I also have a RedBlack
- monarch_dodra (7/63) Nov 21 2013 If the enum's name is RedBlack, and you want the Black value,
- Steve Teale (4/6) Nov 22 2013 Sounds like most of us should be in D Learn on this topic.
- monarch_dodra (9/16) Nov 22 2013 The "problem" with this approach though, is that if you import my
- Meta (19/22) Nov 21 2013 Is this what you mean?
- Steve Teale (19/22) Nov 21 2013 Phobos is less picky than the compiler. Try this:
- Daniel Kozak (42/61) Nov 21 2013 I don't think it would be a good idea to let a compiler decide
- inout (32/51) Nov 21 2013 Because of the follwoing:
- inout (4/62) Nov 21 2013 forgot to add:
- Steve Teale (15/25) Nov 21 2013 I thought that compilers were supposed to help you if you did
- John J (3/18) Nov 21 2013 Compiler helps here by throwing an error.
import std.stdio; enum Intention { EVIL, NEUTRAL, GOOD, SAINTLY } void foo(Intention rth) { if (rth == EVIL) writeln("Road to hell"); } void main() { foo(EVIL); } Why does the compiler complain in both places about EVIL. Can it not work out which EVIL I mean? There's only one choice.
Nov 20 2013
On Thursday, 21 November 2013 at 07:22:39 UTC, Steve Teale wrote:import std.stdio; enum Intention { EVIL, NEUTRAL, GOOD, SAINTLY } void foo(Intention rth) { if (rth == EVIL) writeln("Road to hell"); } void main() { foo(EVIL); } Why does the compiler complain in both places about EVIL. Can it not work out which EVIL I mean? There's only one choice.That should be: if( rth == Intention.EVIL ) and foo( Intention.EVIL );
Nov 20 2013
On Thursday, 21 November 2013 at 07:28:14 UTC, Craig Dillabaugh wrote:On Thursday, 21 November 2013 at 07:22:39 UTC, Steve Teale wrote:clipI should also mention, this post likely better belongs in: digitalmars.D.learn That is the best place for questions about how the language works. This forum is more a place for the D Pros to fight it out over what features should/shouldn't be in the langauge.Why does the compiler complain in both places about EVIL. Can it not work out which EVIL I mean? There's only one choice.That should be: if( rth == Intention.EVIL ) and foo( Intention.EVIL );
Nov 20 2013
On Thursday, 21 November 2013 at 07:42:48 UTC, Craig Dillabaugh wrote:I should also mention, this post likely better belongs in: digitalmars.D.learnI don't entirely think so. I think the OP is arguing that D should be able to identify symbol as specific enum's field when used: - in place of function argument when the fn parameters is of enum type - and when comparing for equality with variable of enum type. ie. the lookup of the symbol should be first inside the enum, and the continue normally. There was plan long long time ago to implement it, but I don't remember for which reason it was not. In order to consider this again for implementation I think proper DIP should be written where complete semantics of this should be described. For one I don't know how it should be have if you would have variable of the same name as enum field i.e: enum State { on, off } auto State s; auto on = 1; if (on == on) ? And I think it would be especially confusing when enum which is function parameters has the same field name as local variable on call site: void change (State s) {} void main () { State on = State.off, change (on) }
Nov 21 2013
On Thursday, 21 November 2013 at 08:05:03 UTC, Michal Minich wrote:On Thursday, 21 November 2013 at 07:42:48 UTC, Craig Dillabaugh wrote:Yes, perhaps that was his intention (no pun intended). First few times I used enums in D I was caught because I expected the behavior he is suggesting here would work.I should also mention, this post likely better belongs in: digitalmars.D.learnI don't entirely think so. I think the OP is arguing that D should be able to identify symbol as specific enum's field when used: - in place of function argument when the fn parameters is of enum type - and when comparing for equality with variable of enum type.
Nov 21 2013
On Thursday, 21 November 2013 at 08:37:32 UTC, Craig Dillabaugh wrote:Yes, perhaps that was his intention (no pun intended). First few times I used enums in D I was caught because I expected the behavior he is suggesting here would work.Pun was intended ;=)
Nov 21 2013
On Thursday, 21 November 2013 at 08:05:03 UTC, Michal Minich wrote:On Thursday, 21 November 2013 at 07:42:48 UTC, Craig Dillabaugh wrote:Michal, Well thank you for a sane reply! I've been with D since about 2006, and I prefer to not make a complete fool of myself. I have to admit that the question was asked in anger. I was working on some old code, and saw this large bare enum, so I gave it a qualifier. It then took me about six hours to stubbornly go through the rest of the code to add the qualifier - aargh! Yes, I agree that the circumstances under which the inference could be made may be limited, but in a function where a single argument is an enum name it's really surprising that it is not implemented. Could 'with' be extended to cover enum names do you think? Also a supplementary question - does auto lock out some things like this, are there other examples?I should also mention, this post likely better belongs in: digitalmars.D.learnI don't entirely think so. I think the OP is arguing that D should be able to identify symbol as specific enum's field when used: - in place of function argument when the fn parameters is of enum type - and when comparing for equality with variable of enum type. ie. the lookup of the symbol should be first inside the enum, and the continue normally. There was plan long long time ago to implement it, but I don't remember for which reason it was not. In order to consider this again for implementation I think proper DIP should be written where complete semantics of this should be described. For one I don't know how it should be have if you would have variable of the same name as enum field i.e: enum State { on, off } auto State s; auto on = 1; if (on == on) ? And I think it would be especially confusing when enum which is function parameters has the same field name as local variable on call site: void change (State s) {} void main () { State on = State.off, change (on) }
Nov 21 2013
On 11/21/13 8:48 AM, Steve Teale wrote:Could 'with' be extended to cover enum names do you think? Also a supplementary question - does auto lock out some things like this, are there other examples?Guess it could. One other thing we could do is to make enum namespaces behave like imports. Andrei
Nov 21 2013
On Thursday, 21 November 2013 at 17:39:28 UTC, Andrei Alexandrescu wrote:On 11/21/13 8:48 AM, Steve Teale wrote:+1. I love this idea. Verbosity only when necessary.Could 'with' be extended to cover enum names do you think? Also a supplementary question - does auto lock out some things like this, are there other examples?Guess it could. One other thing we could do is to make enum namespaces behave like imports. Andrei
Nov 21 2013
On Thursday, 21 November 2013 at 17:39:28 UTC, Andrei Alexandrescu wrote:On 11/21/13 8:48 AM, Steve Teale wrote:I'd love to understand "make enum namespaces behave like imports", but I should probably ask that on D Learn ;=)Could 'with' be extended to cover enum names do you think? Also a supplementary question - does auto lock out some things like this, are there other examples?Guess it could. One other thing we could do is to make enum namespaces behave like imports. Andrei
Nov 21 2013
On Thursday, 21 November 2013 at 18:44:39 UTC, Steve Teale wrote:On Thursday, 21 November 2013 at 17:39:28 UTC, Andrei Alexandrescu wrote:When you import from a module, you only need to specify the module name if there is ambiguity. So for example: //---- import std.array; void main() { split("hello"); //OK! } //---- import std.array; import std.algorithm; void main() { split("hello"); //Wait... did you want std.algorithm.split, or std.array.split? std.array.split("hello"); //OK! That's clearer now. } //---- What Andrei is saying is that an enum *could* work the same way: enum RedBlack //For red black trees { Red, Black, } enum BlackWhite //For Checker boards { Black, White, } void main() { writeln(Red); //OK! No problem! writeln(Black); //I'm sorry... that's ambiguous :/ writeln(RedBlack.Black); //OK! That's clearer now! } Whether or not it *should*, I don't know. "Why not?" I like to say :)On 11/21/13 8:48 AM, Steve Teale wrote:I'd love to understand "make enum namespaces behave like imports", but I should probably ask that on D Learn ;=)Could 'with' be extended to cover enum names do you think? Also a supplementary question - does auto lock out some things like this, are there other examples?Guess it could. One other thing we could do is to make enum namespaces behave like imports. Andrei
Nov 21 2013
On 11/21/2013 02:20 PM, monarch_dodra wrote:When you import from a module, you only need to specify the module name if there is ambiguity. So for example: //---- import std.array; void main() { split("hello"); //OK! } //---- import std.array; import std.algorithm; void main() { split("hello"); //Wait... did you want std.algorithm.split, or std.array.split? std.array.split("hello"); //OK! That's clearer now. } //---- What Andrei is saying is that an enum *could* work the same way: enum RedBlack //For red black trees { Red, Black, } enum BlackWhite //For Checker boards { Black, White, } void main() { writeln(Red); //OK! No problem! writeln(Black); //I'm sorry... that's ambiguous :/ writeln(RedBlack.Black); //OK! That's clearer now! } Whether or not it *should*, I don't know. "Why not?" I like to say :)If both these enums are coming from a module and I also have a RedBlack enum in my main program that has Black in it, then I guess it would be modulename.RedBlack.Black to call the one from the module. Does it make sense? I should be really in D.learn but asked that here in context ;)
Nov 21 2013
On Friday, 22 November 2013 at 00:50:25 UTC, John J wrote:On 11/21/2013 02:20 PM, monarch_dodra wrote:If the enum's name is RedBlack, and you want the Black value, than yes., you'd need to "double disambiguate". If you wanted Red though, then: modulename.Red Should be enough to un-ambiguously refer to the correct enum value.When you import from a module, you only need to specify the module name if there is ambiguity. So for example: //---- import std.array; void main() { split("hello"); //OK! } //---- import std.array; import std.algorithm; void main() { split("hello"); //Wait... did you want std.algorithm.split, or std.array.split? std.array.split("hello"); //OK! That's clearer now. } //---- What Andrei is saying is that an enum *could* work the same way: enum RedBlack //For red black trees { Red, Black, } enum BlackWhite //For Checker boards { Black, White, } void main() { writeln(Red); //OK! No problem! writeln(Black); //I'm sorry... that's ambiguous :/ writeln(RedBlack.Black); //OK! That's clearer now! } Whether or not it *should*, I don't know. "Why not?" I like to say :)If both these enums are coming from a module and I also have a RedBlack enum in my main program that has Black in it, then I guess it would be modulename.RedBlack.Black to call the one from the module. Does it make sense? I should be really in D.learn but asked that here in context ;)
Nov 21 2013
Does it make sense? I should be really in D.learn but asked that here in context ;)Sounds like most of us should be in D Learn on this topic. I should find the time to write up a case for Andrei's suggestion. I have no problem with the compiler telling me that my code is ambiguous, in fact I depend on it!
Nov 22 2013
On Friday, 22 November 2013 at 17:34:09 UTC, Steve Teale wrote:The "problem" with this approach though, is that if you import my module, and I introduce a new enum in my module, I could *break* your code by introducing ambiguity. Not that it's any different from adding functions in modules, that could create ambiguity of course. That said, functions have a "tendency" of not actually being ambiguous thanks to the fact that they overload on their arguments. enums on the other hand, have *no* contextual information to disambiguate.Does it make sense? I should be really in D.learn but asked that here in context ;)Sounds like most of us should be in D Learn on this topic. I should find the time to write up a case for Andrei's suggestion. I have no problem with the compiler telling me that my code is ambiguous, in fact I depend on it!
Nov 22 2013
On Thursday, 21 November 2013 at 16:48:59 UTC, Steve Teale wrote:Could 'with' be extended to cover enum names do you think? Also a supplementary question - does auto lock out some things like this, are there other examples?Is this what you mean? enum Intention { EVIL, NEUTRAL, GOOD, SAINTLY, } void main() { with (Intention) { assert(EVIL == 0); assert(NEUTRAL == 1); assert(GOOD == 2); assert(SAINTLY == 3); } }
Nov 21 2013
That should be: if( rth == Intention.EVIL ) and foo( Intention.EVIL );Phobos is less picky than the compiler. Try this: import std.stdio; enum Intention { EVIL, NEUTRAL, GOOD, SAINTLY } void foo(Intention rth) { if (rth == Intention.EVIL) writefln("The road to hell is paved with %s and %d", rth, rth); } void main() { foo(Intention.EVIL); }
Nov 21 2013
On Thursday, 21 November 2013 at 07:22:39 UTC, Steve Teale wrote:import std.stdio; enum Intention { EVIL, NEUTRAL, GOOD, SAINTLY } void foo(Intention rth) { if (rth == EVIL) writeln("Road to hell"); } void main() { foo(EVIL); } Why does the compiler complain in both places about EVIL. Can it not work out which EVIL I mean? There's only one choice.I don't think it would be a good idea to let a compiler decide which symbol I mean :). So you must use Intention.EVIL instead of just EVIL. Or you can do some trick like this: enum Intention : int {_} enum : Intention { EVIL = cast(Intention)0, NEUTRAL = cast(Intention)1, GOOD = cast(Intention)2, SAINTLY = cast(Intention)3, } void foo(Intention rth) { if (rth == EVIL) writeln("Road to hell"); } void main() { foo(EVIL); } or use aliases: enum Intention { EVIL, NEUTRAL, GOOD, SAINTLY, } alias EVIL = Intention.EVIL; alias NEUTRAL = Intention.NEUTRAL; alias GOOD = Intention.GOOD; alias SAINTLY = Intention.SAINTLY; void foo(Intention rth) { if (rth == EVIL) writeln("Road to hell"); } void main() { foo(EVIL); }
Nov 21 2013
On Thursday, 21 November 2013 at 07:22:39 UTC, Steve Teale wrote:import std.stdio; enum Intention { EVIL, NEUTRAL, GOOD, SAINTLY } void foo(Intention rth) { if (rth == EVIL) writeln("Road to hell"); } void main() { foo(EVIL); } Why does the compiler complain in both places about EVIL. Can it not work out which EVIL I mean? There's only one choice.Because of the follwoing: import foo.bar; enum Intention { EVIL, NEUTRAL, GOOD, SAINTLY } void foo(Intention rth) { ... } void main() { // imagine that this works foo(EVIL); } module foo.bar; // someone else adds this later enum OtherIntention { EVIL, NEUTRAL, GOOD, SAINTLY } BOOM! Code no longer compiles. As a rule, the code that compiles and works should preserve its behavior when new code is added, so this is prohibited. Also please post to D.learn
Nov 21 2013
On Thursday, 21 November 2013 at 17:19:18 UTC, inout wrote:On Thursday, 21 November 2013 at 07:22:39 UTC, Steve Teale wrote:forgot to add: void foo(OtherIntention rth) { ... } Which of the two is being called by main?import std.stdio; enum Intention { EVIL, NEUTRAL, GOOD, SAINTLY } void foo(Intention rth) { if (rth == EVIL) writeln("Road to hell"); } void main() { foo(EVIL); } Why does the compiler complain in both places about EVIL. Can it not work out which EVIL I mean? There's only one choice.Because of the follwoing: import foo.bar; enum Intention { EVIL, NEUTRAL, GOOD, SAINTLY } void foo(Intention rth) { ... } void main() { // imagine that this works foo(EVIL); } module foo.bar; // someone else adds this later enum OtherIntention { EVIL, NEUTRAL, GOOD, SAINTLY } BOOM! Code no longer compiles. As a rule, the code that compiles and works should preserve its behavior when new code is added, so this is prohibited. Also please post to D.learn
Nov 21 2013
I thought that compilers were supposed to help you if you did ambiguous things. An interesting example is: int bar(int n) { return n+1; } int bar(int n) { return n+2; } void main() { int v = 22; int n = bar(22); }BOOM! Code no longer compiles. As a rule, the code that compiles and works should preserve its behavior when new code is added, so this is prohibited. Also please post to D.learnforgot to add: void foo(OtherIntention rth) { ... } Which of the two is being called by main?
Nov 21 2013
On 11/21/2013 01:36 PM, Steve Teale wrote:I thought that compilers were supposed to help you if you did ambiguous things. An interesting example is: int bar(int n) { return n+1; } int bar(int n) { return n+2; } void main() { int v = 22; int n = bar(22); }Compiler helps here by throwing an error. Those are two duplicate functions with same exact arguments.
Nov 21 2013