digitalmars.D.learn - D: Unexpected output when using a delegate and EnumMembers
- Travis Gockel <travis gockelhut.com> Jun 19 2012
- Artur Skawina <art.08.09 gmail.com> Jun 19 2012
- Timon Gehr <timon.gehr gmx.ch> Jun 19 2012
- Artur Skawina <art.08.09 gmail.com> Jun 19 2012
- Timon Gehr <timon.gehr gmx.ch> Jun 19 2012
- Travis Gockel <travis gockelhut.com> Jun 19 2012
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.
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: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.)
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.[1] I don't do that new kinky lambda syntax, sorry. ;)
Your embarrassment about this issue is justifiable.
my compiler doesn't support them... artur
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









Timon Gehr <timon.gehr gmx.ch> 