www.digitalmars.com         C & C++   DMDScript  

D - Cool foreach loops

reply Bill Cox <Bill_member pathlink.com> writes:
Hi.

I've been playing with foreach itterator syntax a bit.  This mechanism is
complex, but very nice to use.  If it's not too complex to implement, I think it
might be a nice enhancement to D.

Here's how it works.  In a container class, or any class that needs an itterator
over children, define a loop function.  Here's an example for directed graphs:

class Node {
Edge firstIn, firstOut;
// This itterates through in edges
loop inEdges(Edge edge) {
for(edge = firstIn; edge != null; edge = edge.nextInEdge) {
doloop;
}
}
// This itterates through out edges
loop outEdges(Edge edge) {
for(edge = firstOut; edge != null; edge = edge.nextOutEdge) {
doloop;
}
}
// This itterates through all edges
loop edges(Edge edge) {
foreach(inEdges, edge) {
doloop;
}
foreach(outEdges, edge) {
doloop;
}
}
}

The foreach loops specify a loop function, and a loop variable.  The compiler
can inline the loop functions to generate the expected code

Bill
Feb 03 2003
parent reply Daniel Yokomiso <Daniel_member pathlink.com> writes:
In article <b1nrjp$1032$1 digitaldaemon.com>, Bill Cox says...
Hi.

I've been playing with foreach itterator syntax a bit.  This mechanism is
complex, but very nice to use.  If it's not too complex to implement, I think it
might be a nice enhancement to D.

Here's how it works.  In a container class, or any class that needs an itterator
over children, define a loop function.  Here's an example for directed graphs:

class Node {
Edge firstIn, firstOut;
// This itterates through in edges
loop inEdges(Edge edge) {
for(edge = firstIn; edge != null; edge = edge.nextInEdge) {
doloop;
}
}
// This itterates through out edges
loop outEdges(Edge edge) {
for(edge = firstOut; edge != null; edge = edge.nextOutEdge) {
doloop;
}
}
// This itterates through all edges
loop edges(Edge edge) {
foreach(inEdges, edge) {
doloop;
}
foreach(outEdges, edge) {
doloop;
}
}
}

The foreach loops specify a loop function, and a loop variable.  The compiler
can inline the loop functions to generate the expected code

Bill
It looks very similar to Sather iterators, but less powerful, because it can iterate only over one iterator. There's some useful info at: http://www.icsi.berkeley.edu/~sather/Documentation/IteratorTutorial/ http://www.icsi.berkeley.edu/~sather/index.html http://www.cs.waikato.ac.nz/sather/
Feb 04 2003
parent reply Bill Cox <bill viasic.com> writes:
Hi, Daniel.

The Sather itterators seem less powerful.  With the loop functions 
illustrated below, it's possible to eliminate one of the most common 
need for function pointers in C: passing callbacks to complex data 
traversal routines.

With this itterator syntax, you could create itterators that traverse 
binary trees, doing the loop body for each node.  The code is easy to 
write and read.  Doing this in Sather is comparitively ugly, and less 
efficient.

Bill

Daniel Yokomiso wrote:
 In article <b1nrjp$1032$1 digitaldaemon.com>, Bill Cox says...
 
Hi.

I've been playing with foreach itterator syntax a bit.  This mechanism is
complex, but very nice to use.  If it's not too complex to implement, I think it
might be a nice enhancement to D.

Here's how it works.  In a container class, or any class that needs an itterator
over children, define a loop function.  Here's an example for directed graphs:

class Node {
Edge firstIn, firstOut;
// This itterates through in edges
loop inEdges(Edge edge) {
for(edge = firstIn; edge != null; edge = edge.nextInEdge) {
doloop;
}
}
// This itterates through out edges
loop outEdges(Edge edge) {
for(edge = firstOut; edge != null; edge = edge.nextOutEdge) {
doloop;
}
}
// This itterates through all edges
loop edges(Edge edge) {
foreach(inEdges, edge) {
doloop;
}
foreach(outEdges, edge) {
doloop;
}
}
}

The foreach loops specify a loop function, and a loop variable.  The compiler
can inline the loop functions to generate the expected code

Bill
It looks very similar to Sather iterators, but less powerful, because it can iterate only over one iterator. There's some useful info at: http://www.icsi.berkeley.edu/~sather/Documentation/IteratorTutorial/ http://www.icsi.berkeley.edu/~sather/index.html http://www.cs.waikato.ac.nz/sather/
Feb 12 2003
parent Daniel Yokomiso <Daniel_member pathlink.com> writes:
Hi,

Comments embedded:

In article <3E4A81F1.6080300 viasic.com>, Bill Cox says...
Hi, Daniel.

The Sather itterators seem less powerful.  With the loop functions 
illustrated below, it's possible to eliminate one of the most common 
need for function pointers in C: passing callbacks to complex data 
traversal routines.

With this itterator syntax, you could create itterators that traverse 
binary trees, doing the loop body for each node.  The code is easy to 
write and read.  Doing this in Sather is comparitively ugly, and less 
efficient.

Bill
I don't understand your remarks about Sather-like iterators being "less powerful" or "ugly". Here's your code written using Sather-like iterating constructs (I'm mixing Sather and D syntax): class Node { Edge firstIn, firstOut; // note that ! marks a method as an iterator Edge inEdges!() { Edge edge = firstIn; // while isn't a primitive but a iterator too loop while!(edge != null); yield edge; edge = edge.nextInEdge end } Edge outEdges!() { Edge edge = firstOut; loop while!(edge != null); yield edge; edge = edge.nextOutEdge end } Edge edges!() { loop yield inEdges!(); end loop yield outEdges!(); end } } Iterators can be used to yield values of series: int fibs!() { int a = 0; int b = 1; loop yield a; (a, b) = (b, a + b); // tuple construction/deconstruction is nice ;-) end } They can also be combined in several ways. More than one iterator can be used in the same loop, and the first to end will terminate the loop. There's also input iterators, like: class List { Object get!() { int i = 0; loop while!( i < size()); yield get(i); i++; end } void set!(Object value) { int i = 0; loop while!( i < size()); set(i, value); yield; i++; end } void copy(List other) { loop set!(other.get!()); // ends when either get! or set! quits end } void copyFiltering(List other, bit (*predicate)(Object)) { loop Object value = other.get!(); if (predicate(value)) { set!(value); // not all iterators in the loop // are called every iteration } end } } Your foreach syntax is very similar to CLU, which was the base for Sather iterators, but they went beyond it. There are lots of good iterator examples available and AFAIK they can be compiled to efficient assembly.
Daniel Yokomiso wrote:
 In article <b1nrjp$1032$1 digitaldaemon.com>, Bill Cox says...
 
Hi.

I've been playing with foreach itterator syntax a bit.  This mechanism is
complex, but very nice to use.  If it's not too complex to implement, I think it
might be a nice enhancement to D.

Here's how it works.  In a container class, or any class that needs an itterator
over children, define a loop function.  Here's an example for directed graphs:

class Node {
Edge firstIn, firstOut;
// This itterates through in edges
loop inEdges(Edge edge) {
for(edge = firstIn; edge != null; edge = edge.nextInEdge) {
doloop;
}
}
// This itterates through out edges
loop outEdges(Edge edge) {
for(edge = firstOut; edge != null; edge = edge.nextOutEdge) {
doloop;
}
}
// This itterates through all edges
loop edges(Edge edge) {
foreach(inEdges, edge) {
doloop;
}
foreach(outEdges, edge) {
doloop;
}
}
}

The foreach loops specify a loop function, and a loop variable.  The compiler
can inline the loop functions to generate the expected code

Bill
It looks very similar to Sather iterators, but less powerful, because it can iterate only over one iterator. There's some useful info at: http://www.icsi.berkeley.edu/~sather/Documentation/IteratorTutorial/ http://www.icsi.berkeley.edu/~sather/index.html http://www.cs.waikato.ac.nz/sather/
Best regards, Daniel Yokomiso.
Feb 13 2003