foreach syntax, std.mixin

Bill Baxter wbaxter at gmail.com
Sun Nov 8 12:05:57 PST 2009


On Sun, Nov 8, 2009 at 9:10 AM, dsimcha <dsimcha at yahoo.com> wrote:
> What are the chances that D gets auto tuple unpacking for foreach loops before
> D2 goes gold?  In other words, it would be nice to write:
>
> uint[] foo = [1,2,3,4,5];
> uint[] bar = [6,7,8,9,10];
>
> foreach(a, b; zip(foo, bar)) {
>    // Does what you think it does.
> }

Probably obvious, but if added, it should probably work by means of
.tupleof on the iterated type, rather than by any particular knowledge
of types used in std.range.  And I guess just public members would be
included.

Main down side is that it could introduce ambiguities with explicitly
specified opApply overloads.  If you have an opApply that takes
uint,uint already, which gets used?  Or is it an error?  I not sure
what would be least likely to cause trouble.  One the one hand the
class author should be able to override the behavior, but on the other
hand class users will assume that tuple unpacking works and may be
surprised if it has been overriden to do something different.  So
either rule -- specifc opApply wins, or it's an error -- seems to have
an argument for it.

> Also, how about foreach over ranges with an index variable?  For example:
>
> foreach(index, elem; chain(foo, bar)) {
>   // Does what you think it does.
> }

This will create too many ambiguities if the tuple unpacking is also
implemeted, so I'm agaist it:

foreach(index,elem; zip(arrayOfInts, bar)) {
    // I don't know what this does
}

I think the index variant would better be done as an enumerate()
function like in python. Which does something like
zip(iota(1,bar.length),bar).

> If these aren't going to happen, would it be worth having in Phobos a
> std.mixin module (I've already considered such a thing a few times here) that
> would allow someone writing a range to add goodies like these to structs and
> classes with a single line of code?  For example:

These look less controversial, but I would like having foreach be able
to tease apart structs/tuples.

A further issue, and this may nuke the idea till we have tuple
literals,  is what to do about tuples of tuples.  In python you can do

     for i,(f,b) in enumerate(zip(foo,bar)):

I don't think we want to introduce the bad idea of automatic
flattening yet again just to get this kind of thing to work:

     foreach(i,f,b; enumerate(zip(foo,bar)))

It should really be something like:

     foreach(i,(f,b); enumerate(zip(foo,bar)))

But that requires D get some tuple sytax.  ... Or I suppose it could
be a special syntax in "foreach" for now.

Another approach to disambiguating tuple iteration vs opApply
iteration could be to require tuple parens around the arguments:

     foreach((f,b); zip(foo,bar)) {}  // tuple iteration
     foreach(f,b; zip(foo, bar)) {} // only works if zip returns
something with the right kind of opApply

--bb



More information about the Digitalmars-d mailing list