digitalmars.D - static foreach
- Navin Kumar (3/3) Mar 28 2010 I was going over the D tutorials on tuples and noticed that it's possibl...
- bearophile (36/38) Mar 28 2010 In my dlibs1 I have:
- Navin Kumar (2/2) Mar 28 2010 Thanks. It would still be nice to see full "static foreach" functionali...
- bearophile (8/9) Mar 28 2010 I agree. I have recently written about it:
- so (3/6) Mar 28 2010 Reading it again, how i missed page 34, awesome!
- bearophile (19/20) Mar 28 2010 Page 6 is about The Rule of Least Astonishment, D tries hard (and often ...
- Andrei Alexandrescu (6/15) Mar 28 2010 static foreach was part of the plan until recently, but Walter
- bearophile (7/11) Mar 28 2010 I didn't know this.
- Navin Kumar (2/3) Mar 28 2010 I like the idea of having an intermediate solution like that. D1 curren...
I was going over the D tutorials on tuples and noticed that it's possible to do a "foreach" across the tuple items. I'm assuming this is a compile-time foreach, is that correct? I've been looking for a way to do a compile-time "foreach" for a different problem, namely complete loop unrolling. I have a performance-sensitive "atoi" routine that knows, at compile-time, the length of the string (but not the string itself). I've been thinking of solving this problem using static if(len == 1) { .. } static if(len == 2) { .. } and so on up to len = 22, and not supporting any longer than that. It severely violates the "DRY" principle, and the function becomes a thousand lines of code (and a nightmare to ever change, since changes have to be made 22x times). I would like to solve this problem with a compile-time foreach; how do I do so? "static foreach" is not valid syntax in D.
Mar 28 2010
Navin Kumar:I was going over the D tutorials on tuples and noticed that it's possible to do a "foreach" across the tuple items. I'm assuming this is a compile-time foreach, is that correct?Correct.I would like to solve this problem with a compile-time foreach; how do I do so? "static foreach" is not valid syntax in D.In my dlibs1 I have: template Range(int stop) { static if (stop <= 0) alias Tuple!() Range; else alias Tuple!(Range!(stop-1), stop-1) Range; } /// ditto template Range(int start, int stop) { static if (stop <= start) alias Tuple!() Range; else alias Tuple!(Range!(start, stop-1), stop-1) Range; } /// ditto template Range(int start, int stop, int step) { static assert(step != 0, "Range: step must be != 0"); static if (step > 0) { static if (stop <= start) alias Tuple!() Range; else alias Tuple!(Range!(start, stop-step, step), stop-step) Range; } else { static if (stop >= start) alias Tuple!() Range; else alias Tuple!(Range!(start, stop-step, step), stop-step) Range; } } // End Range!(a,b,c) With that you can unroll loops and push multiple cases inside a switch statement. With a little more work you can unroll in cases where you don't know the number of loops, using a modulus and vision approach. The main problem, baside a bit of bloat at compile time, is that such forach(i; Range!(...)) doesn't work outside functions, as a good static foreach has to. Bye, bearophile
Mar 28 2010
Thanks. It would still be nice to see full "static foreach" functionality so that, as you pointed out, it can be used outside of functions, to add member variables to a struct, for instance. I know people have been using m4 with C to achieve compile-time loops and branches. D's "static if" is vastly superior to m4 because it has access to typeinfo and routines written in D. I'm a little confused, though, why the author chose to overload "foreach" to either be a runtime loop or a compile-time loop based on whether its looping over a tuple or not. It seems it would be more readable to have "static foreach" and simply put a caveat that it's only supported inside functions for now.
Mar 28 2010
Navin Kumar:It seems it would be more readable to have "static foreach" and simply put a caveat that it's only supported inside functions for now.<I agree. I have recently written about it: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=107873 If you see at this document (about half of those ideas are now present in D2) http://s3.amazonaws.com/dconf2007/WalterAndrei.pdf At page 52 you can see that Walter&Andrei too were appreciating the idea of a static foreach. So I presume you will see it in D3 or even sooner :-) I presume it's not a hard thing to implement. But Walter is busy, and Andrei's book was already late. Bye, bearophile
Mar 28 2010
If you see at this document (about half of those ideas are now present in D2) http://s3.amazonaws.com/dconf2007/WalterAndrei.pdfReading it again, how i missed page 34, awesome! -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Mar 28 2010
so:Reading it again, how i missed page 34, awesome!Page 6 is about The Rule of Least Astonishment, D tries hard (and often succeeds) to be uniform, to do the same things when you use the same syntax in different parts of the language. But I have hitted a case, "T : T*" can mean different things when used in a template or in a is(): template IsPointer1(T : T*) { enum bool IsPointer1 = true; } template IsPointer1(T) { enum bool IsPointer1 = false; } template IsPointer2(T) { enum bool IsPointer2 = is(T : T*); } void main() { static assert(IsPointer1!(int*)); static assert(IsPointer2!(int*)); // asserts } This is a dis-uniformity. I have found it only years of using D1, and it has caused me few troubles. Bye, bearophile
Mar 28 2010
On 03/28/2010 05:09 PM, bearophile wrote:Navin Kumar:static foreach was part of the plan until recently, but Walter encountered severe implementation difficulties so we had to abandon it. I agree that it's odd that the same statement iterates at compile-time or run-time depending on the iterated type. AndreiIt seems it would be more readable to have "static foreach" and simply put a caveat that it's only supported inside functions for now.<I agree. I have recently written about it: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=107873 If you see at this document (about half of those ideas are now present in D2) http://s3.amazonaws.com/dconf2007/WalterAndrei.pdf At page 52 you can see that Walter&Andrei too were appreciating the idea of a static foreach. So I presume you will see it in D3 or even sooner :-) I presume it's not a hard thing to implement. But Walter is busy, and Andrei's book was already late. Bye, bearophile
Mar 28 2010
Andrei Alexandrescu:static foreach was part of the plan until recently, but Walter encountered severe implementation difficulties so we had to abandon it.I didn't know this. It looks like a simple thing to implement, but it must be an illusion.I agree that it's odd that the same statement iterates at compile-time or run-time depending on the iterated type.Between implementing a good static foreach that can be used outside functions too, and the current situation, there is an intermediate possibility: to require the prefix keyword "static" before "foreach" when the foreach is done on a tuple, that is when it's static. This changes nothing in the current D2 semantics. But it makes code a little more readable because you can tell apart with no problems the static case of loop on a tuple from the other one. [Later if Walter finds a way to implement, the static foreach can be made richer, for example letting the compiler translate "static foreach (i; 10 .. 20)" in a "static foreach (i; Range!(10, 20))". And even later if Walter is able the whole thing can be allowed outside functions.] Bye, bearophile
Mar 28 2010
bearophile Wrote:[Later if Walter finds a way to implement, the static foreach can be made richer, for example letting the compiler translate "static foreach (i; 10 .. 20)" in a "static foreach (i; Range!(10, 20))". And even later if Walter is able the whole thing can be allowed outside functions.]I like the idea of having an intermediate solution like that. D1 currently supports "foreach(i; Range!(10,20))" inside functions and so a quick solution is to allow "static foreach(i; Range!(10,20))" and "static foreach(i; 10..20)" inside functions.
Mar 28 2010