Repost: make foreach(i, a; range) "just work"

Regan Heath regan at netmail.co.nz
Fri Feb 21 08:41:00 PST 2014


On Fri, 21 Feb 2014 15:35:44 -0000, Jesse Phillips  
<Jesse.K.Phillips+D at gmail.com> wrote:
> You've provided 3 schemes to support this feature. This suggest there  
> are several "right" ways to bring this into the language, while you  
> prefer 1 someone may prefer 3.

Ignore the 3 schemes they were just me thinking about how what I actually  
want will affect built in tuple expansion etc.

I want just 1 thing to change (at this time), an index added to foreach  
over ranges so that it matches arrays, e.g.

	foreach(index, value; range) { }

The code change is likely quite literally just adding an int to the  
foreach handler for ranges, passing it to the foreach body, and  
incrementing it afterwards.  That's it, well, plus the front end code to  
bind the variable.

All I am suggesting is that we take what we currently have:

	foreach([index, ]value; array) { }
	foreach(value; range) { }
	foreach(key, value; tuple) { }

and make this possible too:

	foreach([index, ]value; range) { }


>>> string[double] AA;
>>>
>>> or something similar, the type system no longer helps. But again, this  
>>> seems pretty much uneventful.
>>
>> Perhaps I wasn't clear, this would work fine:
>>
>> string[double] AA;
>> foreach (string v; AA) {} // v is "value"
>> foreach (double k; AA) {} // k is "key"
>>
>> or am I missing the point you're making?
>
> if AA is changed to a double[string], then your value loop iterates on  
> keys and your key loop iterates on values.

No, I was actually suggesting a change here, the compiler would use type  
matching not ordering to assign the variables.  So because 'v' is a  
string, it is bound to the value not the key.


>>>     foreach(i, v1, v2; tuple(0,1).repeat(10).enumerate)
>>>         writeln(i, "\t", v1, "\t", v2);
>>>
>>> This works today! And once enumerate is part of Phobos it will just  
>>> need an import std.range to use it.
>
> I tested all my claims about enumerate. You need it to import std.traits  
> or else is(Largest(...)) will always be false.

Thanks!  Ok, so how is this working?  ahh, ok I think I get it.  enumerate  
returns a range, whose values are Tuples of index/value where value is  
also a tuple so is flattened, and then the whole lot is flattened into the  
foreach.

So, while the range foreach only supports:

	foreach(value; range) { }

value in this case is a flattened tuple of (index, v1, v2, ...)

Yes?

I had completely forgotten about tuple flattening.

I don't think this affects what I actually want to change, we can have:

	foreach(index, value; range) { }

and still flatten tuples into value, you would simply have to provide one  
extra variable to get an index.

Make sense?

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/


More information about the Digitalmars-d mailing list