D: Unexpected output when using a delegate and EnumMembers

Artur Skawina art.08.09 at gmail.com
Tue Jun 19 08:08:16 PDT 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. ;)


More information about the Digitalmars-d-learn mailing list