| Thread overview | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 28, 2010 static foreach | ||||
|---|---|---|---|---|
| ||||
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.
| ||||
March 28, 2010 Re: static foreach | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Navin Kumar | 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 | |||
March 28, 2010 Re: static foreach | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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. | |||
March 28, 2010 Re: static foreach | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Navin Kumar | 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 | |||
March 28, 2010 Re: static foreach | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | > If you see at this document (about half of those ideas are now present in D2) > http://s3.amazonaws.com/dconf2007/WalterAndrei.pdf Reading it again, how i missed page 34, awesome! -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/ | |||
March 28, 2010 Some astonishment [Re: static foreach] | ||||
|---|---|---|---|---|
| ||||
Posted in reply to so | 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
| |||
March 28, 2010 Re: static foreach | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 03/28/2010 05:09 PM, bearophile wrote:
> 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
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.
Andrei
| |||
March 28, 2010 Re: static foreach | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | 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 | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply