Thread overview
Iterating through enumeration
Aug 12, 2012
Alexandr Druzhinin
Aug 12, 2012
simendsjo
Aug 12, 2012
Alexandr Druzhinin
Aug 12, 2012
Jonathan M Davis
Aug 12, 2012
Alexandr Druzhinin
Aug 12, 2012
Era Scarecrow
Aug 12, 2012
Alexandr Druzhinin
Aug 12, 2012
bearophile
Aug 12, 2012
Timon Gehr
Aug 12, 2012
bearophile
August 12, 2012
Hello all.
I have some enum foo { first=1, second=2, fourth=4, sixth=6} and I'd like to go through this enumeration like it:
foreach(m; foo.min..foo.max) {
	bar(m);
}
But without excluding foo.max and correct handle situation when enum identifiers aren't consequentive.

Thanks in advance
August 12, 2012
On Sun, 12 Aug 2012 12:36:21 +0200, Alexandr Druzhinin <drug2004@bk.ru> wrote:

> Hello all.
> I have some enum foo { first=1, second=2, fourth=4, sixth=6} and I'd like to go through this enumeration like it:
> foreach(m; foo.min..foo.max) {
> 	bar(m);
> }
> But without excluding foo.max and correct handle situation when enum identifiers aren't consequentive.
>
> Thanks in advance

Looking for this? http://dlang.org/phobos/std_traits.html#EnumMembers
August 12, 2012
On Sunday, August 12, 2012 17:36:21 Alexandr Druzhinin wrote:
> Hello all.
> I have some enum foo { first=1, second=2, fourth=4, sixth=6} and I'd
> like to go through this enumeration like it:
> foreach(m; foo.min..foo.max) {
> 	bar(m);
> }
> But without excluding foo.max and correct handle situation when enum
> identifiers aren't consequentive.

foreach(m; std.traits.EnumMembers!foo)
    bar(m);

Though be aware that since EnumMembers results in a TypeTuple, the foreach is actually done at compile time, meaning that you'd actually be getting

bar(foo.first);
bar(foo.second);
bar(foo.fourth);
bar(foo.sixth);

Normally, that doesn't matter, but if you try and do fancier stuff, the fact that the foreach is executed at compile time could affect what you're doing, and if want your function to be small (e.g. inlining), then that would cause problems.

- Jonathan M Davis
August 12, 2012
12.08.2012 17:45, Jonathan M Davis пишет:
> On Sunday, August 12, 2012 17:36:21 Alexandr Druzhinin wrote:
>> Hello all.
>> I have some enum foo { first=1, second=2, fourth=4, sixth=6} and I'd
>> like to go through this enumeration like it:
>> foreach(m; foo.min..foo.max) {
>> 	bar(m);
>> }
>> But without excluding foo.max and correct handle situation when enum
>> identifiers aren't consequentive.
>
> foreach(m; std.traits.EnumMembers!foo)
>      bar(m);
>
> Though be aware that since EnumMembers results in a TypeTuple, the foreach is
> actually done at compile time, meaning that you'd actually be getting
>
> bar(foo.first);
> bar(foo.second);
> bar(foo.fourth);
> bar(foo.sixth);
>
> Normally, that doesn't matter, but if you try and do fancier stuff, the fact
> that the foreach is executed at compile time could affect what you're doing,
> and if want your function to be small (e.g. inlining), then that would cause
> problems.
>
> - Jonathan M Davis
>
didn't know about this module, definitly I'll take a look at it, thanks!
August 12, 2012
12.08.2012 17:43, simendsjo пишет:
> On Sun, 12 Aug 2012 12:36:21 +0200, Alexandr Druzhinin <drug2004@bk.ru>
> wrote:
>
>> Hello all.
>> I have some enum foo { first=1, second=2, fourth=4, sixth=6} and I'd
>> like to go through this enumeration like it:
>> foreach(m; foo.min..foo.max) {
>>     bar(m);
>> }
>> But without excluding foo.max and correct handle situation when enum
>> identifiers aren't consequentive.
>>
>> Thanks in advance
>
> Looking for this? http://dlang.org/phobos/std_traits.html#EnumMembers
Yes, this is what I need, thanks!
August 12, 2012
On Sunday, 12 August 2012 at 10:45:37 UTC, Jonathan M Davis wrote:
> Though be aware that since EnumMembers results in a TypeTuple, the foreach is actually done at compile time, meaning that you'd actually be getting
>
> bar(foo.first);
> bar(foo.second);
> bar(foo.fourth);
> bar(foo.sixth);
>
> Normally, that doesn't matter, but if you try and do fancier stuff, the fact that the foreach is executed at compile time could affect what you're doing, and if want your function to be small (e.g. inlining), then that would cause problems.

 But that problem goes away if you turn it into a small array right? (And pass the array to the foreach to cycle over) So throwing that idea out there you get...

foo[] array;

foreach(m; std.traits.EnumMembers!foo)
    array ~= m;

foreach(m; array) {
 //not compiler-time expansion like above
}
August 12, 2012
12.08.2012 18:23, Era Scarecrow пишет:
> On Sunday, 12 August 2012 at 10:45:37 UTC, Jonathan M Davis wrote:
>> Though be aware that since EnumMembers results in a TypeTuple, the
>> foreach is actually done at compile time, meaning that you'd actually
>> be getting
>>
>> bar(foo.first);
>> bar(foo.second);
>> bar(foo.fourth);
>> bar(foo.sixth);
>>
>> Normally, that doesn't matter, but if you try and do fancier stuff,
>> the fact that the foreach is executed at compile time could affect
>> what you're doing, and if want your function to be small (e.g.
>> inlining), then that would cause problems.
>
>   But that problem goes away if you turn it into a small array right?
> (And pass the array to the foreach to cycle over) So throwing that idea
> out there you get...
>
> foo[] array;
>
> foreach(m; std.traits.EnumMembers!foo)
>      array ~= m;
>
> foreach(m; array) {
>   //not compiler-time expansion like above
> }
It's very useful tip, thank you too!
August 12, 2012
Era Scarecrow:

>  But that problem goes away if you turn it into a small array right? (And pass the array to the foreach to cycle over) So throwing that idea out there you get...
>
> foo[] array;
>
> foreach(m; std.traits.EnumMembers!foo)
>     array ~= m;
>
> foreach(m; array) {
>  //not compiler-time expansion like above
> }

Often better (but every time builds an array on the heap):

foreach (m; [EnumMembers!Foo]) { // Not a static foreach
}

Bye,
bearophile
August 12, 2012
On 08/12/2012 01:54 PM, bearophile wrote:
> Era Scarecrow:
>
>> But that problem goes away if you turn it into a small array right?
>> (And pass the array to the foreach to cycle over) So throwing that
>> idea out there you get...
>>
>> foo[] array;
>>
>> foreach(m; std.traits.EnumMembers!foo)
>> array ~= m;
>>
>> foreach(m; array) {
>> //not compiler-time expansion like above
>> }
>
> Often better (but every time builds an array on the heap):
>
> foreach (m; [EnumMembers!Foo]) { // Not a static foreach
> }
>
> Bye,
> bearophile

This builds the array once at compile time:

static immutable members = [EnumMembers!Foo];
foreach(m; members){

}
August 12, 2012
Timon Gehr:

> This builds the array once at compile time:
>
> static immutable members = [EnumMembers!Foo];
> foreach(m; members){
>
> }

Right:

import std.traits;
enum Foo { A, B, C, D, E, F }
int main() {
    static immutable members = [EnumMembers!Foo];
    int count = 0;
    foreach (m; members) count++;
    foreach (m; members) count++;
    return count;
}


__Dmain:
        push EAX
        xor EAX, EAX
        xor EDX, EDX
        cmp _D4temp4mainFZi7membersyAE4temp3Foo, EAX
        je  L17
LD:     inc EAX
        inc EDX
        cmp EDX, _D4temp4mainFZi7membersyAE4temp3Foo
        jb  LD
L17:    xor EDX, EDX
        cmp _D4temp4mainFZi7membersyAE4temp3Foo, EDX
        je  L2B
L21:    inc EAX
        inc EDX
        cmp EDX, _D4temp4mainFZi7membersyAE4temp3Foo
        jb  L21
L2B:    pop ECX
        ret

Bye,
bearophile