www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - foreach(r; requests) { r.concider(); }

reply Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
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
next sibling parent reply mta`chrono <chrono mta-international.net> writes:
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
next sibling parent Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
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=
ady
 implement 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=
,
 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=
teln(r);
 } };
 =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=
n
 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
prev sibling parent Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
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=
ady
 implement 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=
,
 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=
teln(r);
 } };
 =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=
n
 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
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
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
parent reply Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
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:

 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=
teln(r); } };
 =A0 =A0 unittest { printRange(foreach(i; 0..100)); }
Is this the same? unittest { printRange(std.range.iota(100)); } Bye, bearophile
Oct 12 2011
parent reply bearophile writes:
Gor Gyolchanyan:

 no, yours will print
 1
 0
 0
 
 mine will print
 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 ...
 100
With 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
parent Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
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
 ...
 100
With 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
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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=2498
 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).
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
next sibling parent Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
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:

 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=3D2498
 Here'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=
eln(r);
 } };
 =A0 =A0unittest { printRange(foreach(i; 0..100)); }
This is not a good idea, since translating from an opApply loop to a rang=
e
 is not possible without spawning a new thread or copying the data.

 The reason is simple -- foreach loops using opApply execute in the contex=
t
 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
prev sibling parent reply travert phare.normalesup.org (Christophe) writes:
"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
next sibling parent Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
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
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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=
t
 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 =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
parent Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
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=
all
 a 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