foreach(r; requests) { r.concider(); }

Gor Gyolchanyan gor.f.gyolchanyan at gmail.com
Wed Oct 12 07:36:01 PDT 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 at yahoo.com> wrote:
> On Wed, 12 Oct 2011 03:55:36 -0400, Gor Gyolchanyan
> <gor.f.gyolchanyan at 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
>


More information about the Digitalmars-d mailing list