digitalmars.D - foreach(r; requests) { r.concider(); }
- Gor Gyolchanyan (47/47) Oct 12 2011 The foreach loop is truly a marvelous tool, which allows one to
- mta`chrono (19/66) Oct 12 2011 I understand that you've suggested a different approach. But you can
- Gor Gyolchanyan (11/81) Oct 12 2011 Well, yeah. This is a fairly good workaround, but it's a workaround none...
- Gor Gyolchanyan (8/78) Oct 12 2011 Actually, it's easier, then that, because you can construct and return
- bearophile (5/10) Oct 12 2011 Is this the same?
- Gor Gyolchanyan (22/32) Oct 12 2011 no, yours will print
- bearophile (20/40) Oct 12 2011 With DMD 2.055 this code:
- Gor Gyolchanyan (3/43) Oct 12 2011 Ok. but this isn't flexible.
- Steven Schveighoffer (56/91) Oct 12 2011 You can already do this.
- Gor Gyolchanyan (9/100) Oct 12 2011 Excellent solution! I like it a lot.
- travert phare.normalesup.org (Christophe) (44/44) Nov 04 2011 "Steven Schveighoffer" , dans le message (digitalmars.D:146563), a
- Gor Gyolchanyan (4/48) Nov 04 2011 This is perfect! No need for extra syntax :-)
- Steven Schveighoffer (14/58) Nov 04 2011 t
- Gor Gyolchanyan (8/71) Nov 04 2011 Actually, i didn't think of it before. Good point.
The foreach loop is truly a marvelous tool, which allows one to implement custom iterations, which look and feel just like all other kinds of iterations. The only philosophical problem with it is, that it thinks that only classes and structs can be looped over in a custom way and that they can have only one way to be iterated over. It would be great to be able to implement iterative algorithms for arbitrary types (templated iterations), like strided iteration to extract the red part of an image. It would also be great to be able to have more, then one kind of iteration for every type of iterable. Here's the list of what I mean by that: 1. Allow passing parameters to iterables in foreach: foreach(c, i; MyType(), 3) { } the `3` would be passed to MyType's opApply right after the delegate (of such an overload of opApply is available, of course). 2. Allow named foreach loops: foreach strided(c, i, MyType, 3) { } the `strided` is passed as a template parameter to the opApplly, which (depending on what overloads of opApply are available) may be optional. 3. Allow free-function opApply, which could be templated to work with any kind of iterable in a specific way: int opApply(string name : "strided", Iterable)(Iterable iterable, int delegate(ForeachParamsTuple!Iterable) dg, size_t stride) { /* ... */ } this function would allow you to add stride to any iterable. the `ForeachParamsTuple` will return the tuple of parameters of the given iterable type. 4. Allow foreach loops with a single iterator to be specified without a body, in which case it would return an input range (or some other type of range), lazily evaluating and returning the iterator. void printRange(Range)(Range range) { foreach(r, range) { writeln(r); } }; unittest { printRange(foreach(i; 0..100)); } This would vastly improve the usability and performance of iterable types and ranges, since you no longer need to cache and copy around the data and you don't need to wrap it around delegating structs or classes either. The overloaded opApplies could be allowed to construct and return those ranges themselves. Yes, i know, you might have some questions like "but <this> wouldn't work with <that>." I thought it out pretty carefully and the details are numerous, so I'd rather just answer those questions as they occur, instead of listing them all here. Given these four improvements iterations would become very easy and powerful. The iterations would become very flexible and easily used with range-based algorithms.
Oct 12 2011
I understand that you've suggested a different approach. But you can already implement some kind of custom iterations. Just create a function that returns this. class CustomDataClass { public typeof(this) filter(Color col) { // ... return this; } void opApply(....) ... } auto datas = CustomDataClass(); foreach(u, i; datas.filter(Color.Red)) { // ... } ---------------- Am 12.10.2011 09:55, schrieb Gor Gyolchanyan:The foreach loop is truly a marvelous tool, which allows one to implement custom iterations, which look and feel just like all other kinds of iterations. The only philosophical problem with it is, that it thinks that only classes and structs can be looped over in a custom way and that they can have only one way to be iterated over. It would be great to be able to implement iterative algorithms for arbitrary types (templated iterations), like strided iteration to extract the red part of an image. It would also be great to be able to have more, then one kind of iteration for every type of iterable. Here's the list of what I mean by that: 1. Allow passing parameters to iterables in foreach: foreach(c, i; MyType(), 3) { } the `3` would be passed to MyType's opApply right after the delegate (of such an overload of opApply is available, of course). 2. Allow named foreach loops: foreach strided(c, i, MyType, 3) { } the `strided` is passed as a template parameter to the opApplly, which (depending on what overloads of opApply are available) may be optional. 3. Allow free-function opApply, which could be templated to work with any kind of iterable in a specific way: int opApply(string name : "strided", Iterable)(Iterable iterable, int delegate(ForeachParamsTuple!Iterable) dg, size_t stride) { /* ... */ } this function would allow you to add stride to any iterable. the `ForeachParamsTuple` will return the tuple of parameters of the given iterable type. 4. Allow foreach loops with a single iterator to be specified without a body, in which case it would return an input range (or some other type of range), lazily evaluating and returning the iterator. void printRange(Range)(Range range) { foreach(r, range) { writeln(r); } }; unittest { printRange(foreach(i; 0..100)); } This would vastly improve the usability and performance of iterable types and ranges, since you no longer need to cache and copy around the data and you don't need to wrap it around delegating structs or classes either. The overloaded opApplies could be allowed to construct and return those ranges themselves. Yes, i know, you might have some questions like "but<this> wouldn't work with<that>." I thought it out pretty carefully and the details are numerous, so I'd rather just answer those questions as they occur, instead of listing them all here. Given these four improvements iterations would become very easy and powerful. The iterations would become very flexible and easily used with range-based algorithms.
Oct 12 2011
Well, yeah. This is a fairly good workaround, but it's a workaround nonethe= less. The existence of this workaround makes this request less prioritized, no do= ubt. But it's still much cleaner and less prone to run-time overhead. On Wed, Oct 12, 2011 at 12:13 PM, mta`chrono <chrono mta-international.net> wrote:I understand that you've suggested a different approach. But you can alre=adyimplement some kind of custom iterations. Just create a function that returns this. class CustomDataClass { =A0 =A0 =A0public typeof(this) filter(Color col) =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0 // ... =A0 =A0 =A0 =A0 =A0 =A0 return this; =A0 =A0 =A0} =A0 =A0 =A0void opApply(....) ... } auto datas =3D CustomDataClass(); foreach(u, i; datas.filter(Color.Red)) { =A0 =A0 // ... } ---------------- Am 12.10.2011 09:55, schrieb Gor Gyolchanyan:,The foreach loop is truly a marvelous tool, which allows one to implement custom iterations, which look and feel just like all other kinds of iterations. The only philosophical problem with it is, that it thinks that only classes and structs can be looped over in a custom way and that they can have only one way to be iterated over. It would be great to be able to implement iterative algorithms for arbitrary types (templated iterations), like strided iteration to extract the red part of an image. It would also be great to be able to have more, then one kind of iteration for every type of iterable. Here's the list of what I mean by that: 1. Allow passing parameters to iterables in foreach: =A0 =A0 foreach(c, i; MyType(), 3) { } =A0 =A0 the `3` would be passed to MyType's opApply right after the delegate (of such an overload of opApply is available, of course). 2. Allow named foreach loops: =A0 =A0 foreach strided(c, i, MyType, 3) { } =A0 =A0 the `strided` is passed as a template parameter to the opApplly, which (depending on what overloads of opApply are available) may be optional. 3. Allow free-function opApply, which could be templated to work with any kind of iterable in a specific way: =A0 =A0 int opApply(string name : "strided", Iterable)(Iterable iterable=teln(r);int delegate(ForeachParamsTuple!Iterable) dg, size_t stride) { /* ... */ } =A0 =A0 this function would allow you to add stride to any iterable. the `ForeachParamsTuple` will return the tuple of parameters of the given iterable type. 4. Allow foreach loops with a single iterator to be specified without a body, in which case it would return an input range (or some other type of range), lazily evaluating and returning the iterator. =A0 =A0 void printRange(Range)(Range range) { foreach(r, range) { =A0wri=n} }; =A0 =A0 unittest { printRange(foreach(i; 0..100)); } =A0 =A0 This would vastly improve the usability and performance of iterable types and ranges, since you no longer need to cache and copy around the data and you don't need to wrap it around delegating structs or classes either. =A0 =A0 The overloaded opApplies could be allowed to construct and retur=those ranges themselves. Yes, i know, you might have some questions like "but<this> =A0wouldn't work with<that>." I thought it out pretty carefully and the details are numerous, so I'd rather just answer those questions as they occur, instead of listing them all here. Given these four improvements iterations would become very easy and powerful. The iterations would become very flexible and easily used with range-based algorithms.
Oct 12 2011
Actually, it's easier, then that, because you can construct and return delegates. On Wed, Oct 12, 2011 at 12:13 PM, mta`chrono <chrono mta-international.net> wrote:I understand that you've suggested a different approach. But you can alre=adyimplement some kind of custom iterations. Just create a function that returns this. class CustomDataClass { =A0 =A0 =A0public typeof(this) filter(Color col) =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0 // ... =A0 =A0 =A0 =A0 =A0 =A0 return this; =A0 =A0 =A0} =A0 =A0 =A0void opApply(....) ... } auto datas =3D CustomDataClass(); foreach(u, i; datas.filter(Color.Red)) { =A0 =A0 // ... } ---------------- Am 12.10.2011 09:55, schrieb Gor Gyolchanyan:,The foreach loop is truly a marvelous tool, which allows one to implement custom iterations, which look and feel just like all other kinds of iterations. The only philosophical problem with it is, that it thinks that only classes and structs can be looped over in a custom way and that they can have only one way to be iterated over. It would be great to be able to implement iterative algorithms for arbitrary types (templated iterations), like strided iteration to extract the red part of an image. It would also be great to be able to have more, then one kind of iteration for every type of iterable. Here's the list of what I mean by that: 1. Allow passing parameters to iterables in foreach: =A0 =A0 foreach(c, i; MyType(), 3) { } =A0 =A0 the `3` would be passed to MyType's opApply right after the delegate (of such an overload of opApply is available, of course). 2. Allow named foreach loops: =A0 =A0 foreach strided(c, i, MyType, 3) { } =A0 =A0 the `strided` is passed as a template parameter to the opApplly, which (depending on what overloads of opApply are available) may be optional. 3. Allow free-function opApply, which could be templated to work with any kind of iterable in a specific way: =A0 =A0 int opApply(string name : "strided", Iterable)(Iterable iterable=teln(r);int delegate(ForeachParamsTuple!Iterable) dg, size_t stride) { /* ... */ } =A0 =A0 this function would allow you to add stride to any iterable. the `ForeachParamsTuple` will return the tuple of parameters of the given iterable type. 4. Allow foreach loops with a single iterator to be specified without a body, in which case it would return an input range (or some other type of range), lazily evaluating and returning the iterator. =A0 =A0 void printRange(Range)(Range range) { foreach(r, range) { =A0wri=n} }; =A0 =A0 unittest { printRange(foreach(i; 0..100)); } =A0 =A0 This would vastly improve the usability and performance of iterable types and ranges, since you no longer need to cache and copy around the data and you don't need to wrap it around delegating structs or classes either. =A0 =A0 The overloaded opApplies could be allowed to construct and retur=those ranges themselves. Yes, i know, you might have some questions like "but<this> =A0wouldn't work with<that>." I thought it out pretty carefully and the details are numerous, so I'd rather just answer those questions as they occur, instead of listing them all here. Given these four improvements iterations would become very easy and powerful. The iterations would become very flexible and easily used with range-based algorithms.
Oct 12 2011
Gor Gyolchanyan:4. Allow foreach loops with a single iterator to be specified without a body, in which case it would return an input range (or some other type of range), lazily evaluating and returning the iterator. void printRange(Range)(Range range) { foreach(r, range) { writeln(r); } }; unittest { printRange(foreach(i; 0..100)); }Is this the same? unittest { printRange(std.range.iota(100)); } Bye, bearophile
Oct 12 2011
no, yours will print 1 0 0 mine will print 0 1 2 3 4 5 6 7 8 9 10 11 ... 100 On Wed, Oct 12, 2011 at 12:46 PM, bearophile <bearophileHUGS lycos.com> wro= te:Gor Gyolchanyan:teln(r); } };4. Allow foreach loops with a single iterator to be specified without a body, in which case it would return an input range (or some other type of range), lazily evaluating and returning the iterator. =A0 =A0 void printRange(Range)(Range range) { foreach(r, range) { =A0wri==A0 =A0 unittest { printRange(foreach(i; 0..100)); }Is this the same? unittest { printRange(std.range.iota(100)); } Bye, bearophile
Oct 12 2011
Gor Gyolchanyan:no, yours will print 1 0 0 mine will print 0 1 2 3 4 5 6 7 8 9 10 11 ... 100With DMD 2.055 this code: import std.stdio, std.range; void printRange(Range)(Range range) { foreach (r; range) writeln(r); } void main() { printRange(iota(100)); } Prints: 0 1 2 ... 97 98 99 Bye, bearophile
Oct 12 2011
Ok. but this isn't flexible. On Wed, Oct 12, 2011 at 1:42 PM, bearophile <bearophileHUGS lycos.com> wrot= e:Gor Gyolchanyan:no, yours will print 1 0 0 mine will print 0 1 2 3 4 5 6 7 8 9 10 11 ... 100With DMD 2.055 this code: import std.stdio, std.range; void printRange(Range)(Range range) { =A0 =A0foreach (r; range) =A0 =A0 =A0 =A0writeln(r); } void main() { =A0 =A0printRange(iota(100)); } Prints: 0 1 2 ... 97 98 99 Bye, bearophile
Oct 12 2011
On Wed, 12 Oct 2011 03:55:36 -0400, Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> wrote:The foreach loop is truly a marvelous tool, which allows one to implement custom iterations, which look and feel just like all other kinds of iterations. The only philosophical problem with it is, that it thinks that only classes and structs can be looped over in a custom way and that they can have only one way to be iterated over. It would be great to be able to implement iterative algorithms for arbitrary types (templated iterations), like strided iteration to extract the red part of an image. It would also be great to be able to have more, then one kind of iteration for every type of iterable.You can already do this. struct Iterable { int opApply(int delegate(ref int) dg) { int result = 0; foreach(int i; 0..100) { auto t = i; // I hate this part of opApply BTW. if((result = dg(t)) != 0) break; } return result; } int inReverse(int delegate(ref int) dg) { int result = 0; foreach(int i; 0..100) { auto t = 99-i; if((result = dg(t)) != 0) break; } return result; } } void main() { Interable it; foreach(i; it) {} foreach(i; &it.inReverse) {} } I've proposed an enhancement to make this better: http://d.puremagic.com/issues/show_bug.cgi?id=2498Here's the list of what I mean by that: 1. Allow passing parameters to iterables in foreach: foreach(c, i; MyType(), 3) { } the `3` would be passed to MyType's opApply right after the delegate (of such an overload of opApply is available, of course).This might be useful, but I don't like the syntax. My preference would be to pass the parameters to the function itself, and infer the delegate from the foreach body. i.e.: struct Iterable { int foo(int x, int delegate(ref int) dg) {...} } Iterable it; foreach(i; it.foo(3)) {...} Of course, this syntax is predicated on acceptance of my afore-mentioned enhancement request.2. Allow named foreach loops: foreach strided(c, i, MyType, 3) { } the `strided` is passed as a template parameter to the opApplly, which (depending on what overloads of opApply are available) may be optional.I don't see a large benefit of this over already existing foreach(c, i; &MyType.strided)3. Allow free-function opApply, which could be templated to work with any kind of iterable in a specific way: int opApply(string name : "strided", Iterable)(Iterable iterable, int delegate(ForeachParamsTuple!Iterable) dg, size_t stride) { /* ... */ } this function would allow you to add stride to any iterable. the `ForeachParamsTuple` will return the tuple of parameters of the given iterable type.Again, enhancement 2498 could be used for this.4. Allow foreach loops with a single iterator to be specified without a body, in which case it would return an input range (or some other type of range), lazily evaluating and returning the iterator. void printRange(Range)(Range range) { foreach(r, range) { writeln(r); } }; unittest { printRange(foreach(i; 0..100)); }This is not a good idea, since translating from an opApply loop to a range is not possible without spawning a new thread or copying the data. The reason is simple -- foreach loops using opApply execute in the context of the opApply function, they cannot leave that context, and the context requires full use of the program stack. I don't see a huge benefit of doing this vs.: foreach(i; 0..100) writeln(i); -Steve
Oct 12 2011
Excellent solution! I like it a lot. Your proposal covers for 1, 2 and 3 beautifully and you've convinced me, that 4 won't be as useful as it will be painful. +vote. On Wed, Oct 12, 2011 at 6:15 PM, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Wed, 12 Oct 2011 03:55:36 -0400, Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> wrote:eln(r);The foreach loop is truly a marvelous tool, which allows one to implement custom iterations, which look and feel just like all other kinds of iterations. The only philosophical problem with it is, that it thinks that only classes and structs can be looped over in a custom way and that they can have only one way to be iterated over. It would be great to be able to implement iterative algorithms for arbitrary types (templated iterations), like strided iteration to extract the red part of an image. It would also be great to be able to have more, then one kind of iteration for every type of iterable.You can already do this. struct Iterable { =A0 int opApply(int delegate(ref int) dg) =A0 { =A0 =A0 =A0int result =3D 0; =A0 =A0 =A0foreach(int i; 0..100) =A0 =A0 =A0{ =A0 =A0 =A0 =A0 auto t =3D i; // I hate this part of opApply BTW. =A0 =A0 =A0 =A0 if((result =3D dg(t)) !=3D 0) break; =A0 =A0 =A0} =A0 =A0 =A0return result; =A0 } =A0 int inReverse(int delegate(ref int) dg) =A0 { =A0 =A0 =A0int result =3D 0; =A0 =A0 =A0foreach(int i; 0..100) =A0 =A0 =A0{ =A0 =A0 =A0 =A0 auto t =3D 99-i; =A0 =A0 =A0 =A0 if((result =3D dg(t)) !=3D 0) break; =A0 =A0 =A0} =A0 =A0 =A0return result; =A0 } } void main() { =A0 Interable it; =A0 foreach(i; it) {} =A0 foreach(i; &it.inReverse) {} } I've proposed an enhancement to make this better: http://d.puremagic.com/issues/show_bug.cgi?id=3D2498Here's the list of what I mean by that: 1. Allow passing parameters to iterables in foreach: =A0 =A0foreach(c, i; MyType(), 3) { } =A0 =A0the `3` would be passed to MyType's opApply right after the delegate (of such an overload of opApply is available, of course).This might be useful, but I don't like the syntax. My preference would be to pass the parameters to the function itself, and infer the delegate from the foreach body. =A0i.e.: struct Iterable { =A0 int foo(int x, int delegate(ref int) dg) {...} } Iterable it; foreach(i; it.foo(3)) {...} Of course, this syntax is predicated on acceptance of my afore-mentioned enhancement request.2. Allow named foreach loops: =A0 =A0foreach strided(c, i, MyType, 3) { } =A0 =A0the `strided` is passed as a template parameter to the opApplly, which (depending on what overloads of opApply are available) may be optional.I don't see a large benefit of this over already existing foreach(c, i; &MyType.strided)3. Allow free-function opApply, which could be templated to work with any kind of iterable in a specific way: =A0 =A0int opApply(string name : "strided", Iterable)(Iterable iterable, int delegate(ForeachParamsTuple!Iterable) dg, size_t stride) { /* ... */ } =A0 =A0this function would allow you to add stride to any iterable. the `ForeachParamsTuple` will return the tuple of parameters of the given iterable type.Again, enhancement 2498 could be used for this.4. Allow foreach loops with a single iterator to be specified without a body, in which case it would return an input range (or some other type of range), lazily evaluating and returning the iterator. =A0 =A0void printRange(Range)(Range range) { foreach(r, range) { =A0writ=e} }; =A0 =A0unittest { printRange(foreach(i; 0..100)); }This is not a good idea, since translating from an opApply loop to a rang=is not possible without spawning a new thread or copying the data. The reason is simple -- foreach loops using opApply execute in the contex=tof the opApply function, they cannot leave that context, and the context requires full use of the program stack. I don't see a huge benefit of doing this vs.: foreach(i; 0..100) writeln(i); -Steve
Oct 12 2011
"Steven Schveighoffer" , dans le message (digitalmars.D:146563), a écrit : The foreach delegate syntax already allow you to have parametrized iteration over a structure ! Actually, the delegate do not have to be returned by the & operator, it can be returned by a function. It's a bit awkward first, but then it's easy to use: struct Iterable { int delegate(int delegate(ref int)) inReverse() { return () { int result = 0; foreach(int i; 0..100) { auto t = 99-i; if((result = dg(t)) != 0) break; } return result; } } int delegate(int delegate(ref int)) byStep(int step) { return() { int result = 0; foreach(int i; iota(0, 100, step)) { auto t = i; if((result = dg(t)) != 0) break; } return result; } } } int main() { Iterable it; foreach (i; it.inReverse) writeln(i); foreach (i; it.byStep(2)) writeln(i); } There is no need to add a special syntax to do what you want ! Maybe there should be a bit more documentation about this.
Nov 04 2011
This is perfect! No need for extra syntax :-) Thanks a lot! :-) On Fri, Nov 4, 2011 at 5:01 PM, Christophe <travert phare.normalesup.org> w= rote:"Steven Schveighoffer" , dans le message (digitalmars.D:146563), a =A0=E9crit=A0: The foreach delegate syntax already allow you to have parametrized iteration over a structure ! Actually, the delegate do not have to be returned by the & operator, it can be returned by a function. It's a bit awkward first, but then it's easy to use: struct Iterable { =A0 =A0int delegate(int delegate(ref int)) inReverse() =A0 =A0{ =A0 =A0 =A0 =A0return () =A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0int result =3D 0; =A0 =A0 =A0 =A0 =A0foreach(int i; 0..100) =A0 =A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0 auto t =3D 99-i; =A0 =A0 =A0 =A0 =A0 =A0 if((result =3D dg(t)) !=3D 0) break; =A0 =A0 =A0 =A0 =A0} =A0 =A0 =A0 =A0 =A0return result; =A0 =A0 =A0 =A0} =A0 =A0} =A0 =A0int delegate(int delegate(ref int)) byStep(int step) =A0 =A0{ =A0 =A0 =A0 return() =A0 =A0 =A0 =A0 { =A0 =A0 =A0 =A0 =A0 int result =3D 0; =A0 =A0 =A0 =A0 =A0 foreach(int i; iota(0, 100, step)) =A0 =A0 =A0 =A0 =A0 { =A0 =A0 =A0 =A0 =A0 =A0 =A0auto t =3D i; =A0 =A0 =A0 =A0 =A0 =A0 =A0if((result =3D dg(t)) !=3D 0) break; =A0 =A0 =A0 =A0 =A0 } =A0 =A0 =A0 =A0 =A0 return result; =A0 =A0 =A0 =A0 } =A0 =A0} } int main() { =A0Iterable it; =A0foreach (i; it.inReverse) writeln(i); =A0foreach (i; it.byStep(2)) writeln(i); } There is no need to add a special syntax to do what you want ! Maybe there should be a bit more documentation about this.
Nov 04 2011
On Fri, 04 Nov 2011 09:01:11 -0400, Christophe = <travert phare.normalesup.org> wrote:"Steven Schveighoffer" , dans le message (digitalmars.D:146563), a =C3=A9crit : The foreach delegate syntax already allow you to have parametrized iteration over a structure ! Actually, the delegate do not have to be returned by the & operator, i=tcan be returned by a function. It's a bit awkward first, but then it's=easy to use: struct Iterable { int delegate(int delegate(ref int)) inReverse() { return () { int result =3D 0; foreach(int i; 0..100) { auto t =3D 99-i; if((result =3D dg(t)) !=3D 0) break; } return result; } } int delegate(int delegate(ref int)) byStep(int step) { return() { int result =3D 0; foreach(int i; iota(0, 100, step)) { auto t =3D i; if((result =3D dg(t)) !=3D 0) break; } return result; } } } int main() { Iterable it; foreach (i; it.inReverse) writeln(i); foreach (i; it.byStep(2)) writeln(i); } There is no need to add a special syntax to do what you want ! Maybe there should be a bit more documentation about this.I'll point out first that this solution allocates a closure on the heap = -- = not necessarily the most efficient solution. Second of all, this seems like a *lot* of trouble to go through just to = = call a function (yes, that's all you're doing). The delegate returned i= s = called *once* and then thrown away. I'd much rather the language just support the most straightforward = solution (calling a function with the given parameters). -Steve
Nov 04 2011
Actually, i didn't think of it before. Good point. This is not the most efficient way to iterate over a range in a custom way. On Fri, Nov 4, 2011 at 6:34 PM, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Fri, 04 Nov 2011 09:01:11 -0400, Christophe <travert phare.normalesup.org> wrote:-"Steven Schveighoffer" , dans le message (digitalmars.D:146563), a =A0=E9crit : The foreach delegate syntax already allow you to have parametrized iteration over a structure ! Actually, the delegate do not have to be returned by the & operator, it can be returned by a function. It's a bit awkward first, but then it's easy to use: struct Iterable { =A0 =A0int delegate(int delegate(ref int)) inReverse() =A0 =A0{ =A0 =A0 =A0 =A0return () =A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0int result =3D 0; =A0 =A0 =A0 =A0 =A0foreach(int i; 0..100) =A0 =A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0 auto t =3D 99-i; =A0 =A0 =A0 =A0 =A0 =A0 if((result =3D dg(t)) !=3D 0) break; =A0 =A0 =A0 =A0 =A0} =A0 =A0 =A0 =A0 =A0return result; =A0 =A0 =A0 =A0} =A0 =A0} =A0 =A0int delegate(int delegate(ref int)) byStep(int step) =A0 =A0{ =A0 =A0 =A0 return() =A0 =A0 =A0 =A0 { =A0 =A0 =A0 =A0 =A0 int result =3D 0; =A0 =A0 =A0 =A0 =A0 foreach(int i; iota(0, 100, step)) =A0 =A0 =A0 =A0 =A0 { =A0 =A0 =A0 =A0 =A0 =A0 =A0auto t =3D i; =A0 =A0 =A0 =A0 =A0 =A0 =A0if((result =3D dg(t)) !=3D 0) break; =A0 =A0 =A0 =A0 =A0 } =A0 =A0 =A0 =A0 =A0 return result; =A0 =A0 =A0 =A0 } =A0 =A0} } int main() { =A0Iterable it; =A0foreach (i; it.inReverse) writeln(i); =A0foreach (i; it.byStep(2)) writeln(i); } There is no need to add a special syntax to do what you want ! Maybe there should be a bit more documentation about this.I'll point out first that this solution allocates a closure on the heap -=not necessarily the most efficient solution. Second of all, this seems like a *lot* of trouble to go through just to c=alla function (yes, that's all you're doing). =A0The delegate returned is ca=lled*once* and then thrown away. I'd much rather the language just support the most straightforward soluti=on(calling a function with the given parameters). -Steve
Nov 04 2011