digitalmars.D.learn - D: Unexpected output when using a delegate and EnumMembers
- Travis Gockel (51/51) Jun 19 2012 I have some rather odd behavior in my D program that I've narrowed down ...
- Artur Skawina (9/56) Jun 19 2012 Yes, it can be surprising, but I'm not convinced it's actually wrong
- Timon Gehr (4/11) Jun 19 2012 It is not this bug. (And what is listed there is clearly wrong
- Artur Skawina (7/19) Jun 19 2012 It's not that simple. I remember considering the alternatives when I
- Timon Gehr (12/15) Jun 19 2012 You have found a bug in DMD.
- Travis Gockel (2/4) Jun 19 2012 Reported: http://d.puremagic.com/issues/show_bug.cgi?id=8267
I have some rather odd behavior in my D program that I've narrowed down to this: import std.algorithm; import std.stdio; import std.traits; enum E { a, b, c }; struct S { E e; }; void main() { immutable(S)[] source = [ S(E.a), S(E.a), S(E.b) ]; foreach (e; EnumMembers!E) { size_t c = count!(x => x.e == e)(source); writeln(e, " -> ", c); } } I would expect the output of this program to be something along the lines of: a -> 2 b -> 1 c -> 0 But the actual result is: a -> 2 b -> 2 c -> 2 Curiously, changing the for loop to foreach (e; [ E.a, E.b, E.c ]) produces my expected output. Using foreach (e; [ EnumMembers!E ]) also produces my expected result, so clearly my use of the range from EnumMemebers is the problem here...I just don't know why. By moving the count call to a separate function: size_t counte(Range)(E e, Range src) { return count!(x => x.e == e)(src); } and changing c's initialization to size_t c = counte(e, source);, the program works as I would expect. I am clearly doing something wrong, but I have no idea what and would appreciate some insight. My compiler is DMD64 D Compiler v2.059 on Linux. begin 644 enum_delegate.d M(R$O=7-R+V)I;B]R9&UD" II;7!O<G0 <W1D+F%L9V]R:71H;3L*:6UP;W)T M('-T9"YS=&1I;SL*:6UP;W)T('-T9"YT<F%I=',[" IE;G5M($4 >R!A+"!B M+"!C('T[" IS=')U8W0 4R![($4 93L ?3L*"G-I>F5?="!C;W5N=&4H4F%N M9V4I*$4 92P 4F%N9V4 <W)C*0I["B` ("!R971U<FX 8V]U;G0A*' /3X M>"YE(#T](&4I*'-R8RD["GT*"G9O:60 ;6%I;B I"GL*("` (&EM;75T86)L M92A3*5M=('-O=7)C92`](%L 4RA%+F$I+"!3*$4N82DL(%,H12YB*2!=.PH M("` 9F]R96%C:"`H93L 16YU;4UE;6)E<G,A12D*("` ('L*("` ("` ("!V M97)S:6]N("AC;W5N=&4I"B` ("` ("` ("` ('-I>F5?="!C(#T 8V]U;G1E M*&4L('-O=7)C92D["B` ("` ("` 96QS90H ("` ("` ("` ("!S:7IE7W0 M8R`](&-O=6YT(2AX(#T^(' N92`]/2!E*2AS;W5R8V4I.PH ("` ("` ('=R <:71E;&XH92P (B`M/B`B+"!C*3L*("` ('T*?0`` ` end
Jun 19 2012
On 06/19/12 16:44, Travis Gockel wrote:import std.algorithm; import std.stdio; import std.traits; enum E { a, b, c }; struct S { E e; }; void main() { immutable(S)[] source = [ S(E.a), S(E.a), S(E.b) ]; foreach (e; EnumMembers!E) { size_t c = count!(x => x.e == e)(source); writeln(e, " -> ", c); } } I would expect the output of this program to be something along the lines of: a -> 2 b -> 1 c -> 0 But the actual result is: a -> 2 b -> 2 c -> 2 Curiously, changing the for loop to foreach (e; [ E.a, E.b, E.c ]) produces my expected output. Using foreach (e; [ EnumMembers!E ]) also produces my expected result, so clearly my use of the range from EnumMemebers is the problem here...I just don't know why. By moving the count call to a separate function: size_t counte(Range)(E e, Range src) { return count!(x => x.e == e)(src); } and changing c's initialization to size_t c = counte(e, source);, the program works as I would expect. I am clearly doing something wrong, but I have no idea what and would appreciate some insight.Yes, it can be surprising, but I'm not convinced it's actually wrong behavior (the bug is http://d.puremagic.com/issues/show_bug.cgi?id=2043) Just do this: size_t c = count!(function(x, e) { return x.e == e;} )(source, e); and it will work. [1] artur [1] I don't do that new kinky lambda syntax, sorry. ;)
Jun 19 2012
On 06/19/2012 05:08 PM, Artur Skawina wrote:Yes, it can be surprising, but I'm not convinced it's actually wrong behavior (the bug is http://d.puremagic.com/issues/show_bug.cgi?id=2043)It is not this bug. (And what is listed there is clearly wrong behaviour, because it can be used to break the type system.)Just do this: size_t c = count!(function(x, e) { return x.e == e;} )(source, e); and it will work. [1] artur [1] I don't do that new kinky lambda syntax, sorry. ;)Your embarrassment about this issue is justifiable.
Jun 19 2012
On 06/19/12 17:32, Timon Gehr wrote:On 06/19/2012 05:08 PM, Artur Skawina wrote:It's not that simple. I remember considering the alternatives when I originally ran into this, and they have problems too. The "static foreach" case may be special, possibly.Yes, it can be surprising, but I'm not convinced it's actually wrong behavior (the bug is http://d.puremagic.com/issues/show_bug.cgi?id=2043)It is not this bug. (And what is listed there is clearly wrong behaviour, because it can be used to break the type system.)I'm proud of it. ;) But maybe it has something to do with the fact that my compiler doesn't support them... artur[1] I don't do that new kinky lambda syntax, sorry. ;)Your embarrassment about this issue is justifiable.
Jun 19 2012
On 06/19/2012 04:44 PM, Travis Gockel wrote:I am clearly doing something wrong,You are not.but I have no idea what and would appreciate some insight.You have found a bug in DMD. Reduced test case that should compile: template Seq(T...){alias T Seq;} auto exec(alias a)(){return a();} void main(){ foreach(e; Seq!(0, 1)) static assert(exec!(()=>e)()==e); } You can report the bug here: http://d.puremagic.com/issues/ The 'exec' template is instantiated only once instead of two times.
Jun 19 2012
== Quote from Timon Gehr (timon.gehr gmx.ch)'s articleYou can report the bug here: http://d.puremagic.com/issues/ The 'exec' template is instantiated only once instead of two times.Reported: http://d.puremagic.com/issues/show_bug.cgi?id=8267
Jun 19 2012