Thread overview
Iterating over the tupleof of a struct
Aug 23, 2014
Meta
Aug 23, 2014
Meta
Aug 23, 2014
Dicebot
Aug 23, 2014
Suliman
Aug 23, 2014
Meta
Aug 23, 2014
Ali Çehreli
Aug 23, 2014
Meta
August 23, 2014
Something weird happens when I try to foreach over test.tupleof. If the foreach loop has 2 variables like so:

struct Test
{
	string name = "'null'";
	int id;
}

void main()
{
	auto test = Test();
	assert(test.name == "'null'");
	assert(test.id == 0);
	
	foreach (val1, val2; test.tupleof)
	{
		import std.stdio, std.conv, std.traits;
		writeln(typeof(val1).stringof, "->", val1, " ",
                        typeof(val2).stringof, "->", val2);
	}
}

The following is printed:

ulong->0 string->'null'
ulong->1 int->0



If the foreach only has 1 variable, like this:

	foreach (val; test.tupleof)
	{
		import std.stdio, std.conv, std.traits;
		writeln(typeof(val).stringof, "->", val);
	}

The following is printed instead:

string->'null'
int->0



What is happening here? Are these two extra ulongs the offsets of the fields in the struct?
August 23, 2014
On Saturday, 23 August 2014 at 01:24:10 UTC, Meta wrote:
> What is happening here? Are these two extra ulongs the offsets of the fields in the struct?

And I just realized that that's obviously not the case. It's just an iteration variable. Problem solved.
August 23, 2014
On Saturday, 23 August 2014 at 01:32:13 UTC, Meta wrote:
> On Saturday, 23 August 2014 at 01:24:10 UTC, Meta wrote:
>> What is happening here? Are these two extra ulongs the offsets of the fields in the struct?
>
> And I just realized that that's obviously not the case. It's just an iteration variable. Problem solved.

It is same with arrays:

int[] arr = [ 1, 2, 3 ];

// ok, iterates elements
foreach (elem; arr) { }

// also ok, iterates elements + counts current index
foreach (index, elem; arr) { }
August 23, 2014
How can I feel struct with foreach loop?

struct ConfigStruct
{
    string [string] key1;
    string [string] key2;
}
ConfigStruct confstruct;

foreach (i, line; readText(ConfigName).splitLines())
{
string [] keyvalue = line.split("=");
confstruct.key1[keyvalue[0]] = keyvalue[1];
}

it's ok for 1 key, but I need iterate through all element of struct. For make it's simply let's assume that spited lines are equal йшер number of elements in struct.

August 23, 2014
On Saturday, 23 August 2014 at 01:56:06 UTC, Dicebot wrote:
> On Saturday, 23 August 2014 at 01:32:13 UTC, Meta wrote:
>> On Saturday, 23 August 2014 at 01:24:10 UTC, Meta wrote:
>>> What is happening here? Are these two extra ulongs the offsets of the fields in the struct?
>>
>> And I just realized that that's obviously not the case. It's just an iteration variable. Problem solved.
>
> It is same with arrays:
>
> int[] arr = [ 1, 2, 3 ];
>
> // ok, iterates elements
> foreach (elem; arr) { }
>
> // also ok, iterates elements + counts current index
> foreach (index, elem; arr) { }

Yeah, I got confused as I expected

	foreach (val1, val2; test.tupleof)
	{
		//...
	}

To destructure the result of test.tupleof, but I just got an iteration variable instead.
August 23, 2014
On 08/23/2014 10:21 AM, Meta wrote:
> On Saturday, 23 August 2014 at 01:56:06 UTC, Dicebot wrote:
>> On Saturday, 23 August 2014 at 01:32:13 UTC, Meta wrote:
>>> On Saturday, 23 August 2014 at 01:24:10 UTC, Meta wrote:
>>>> What is happening here? Are these two extra ulongs the offsets of
>>>> the fields in the struct?
>>>
>>> And I just realized that that's obviously not the case. It's just an
>>> iteration variable. Problem solved.
>>
>> It is same with arrays:
>>
>> int[] arr = [ 1, 2, 3 ];
>>
>> // ok, iterates elements
>> foreach (elem; arr) { }
>>
>> // also ok, iterates elements + counts current index
>> foreach (index, elem; arr) { }
>
> Yeah, I got confused as I expected
>
>      foreach (val1, val2; test.tupleof)
>      {
>          //...
>      }
>
> To destructure the result of test.tupleof, but I just got an iteration
> variable instead.

There are a number of inconsistencies around tuples. The behavior you expect is present for ranges that return tuple fronts:

import std.stdio;
import std.typecons;
import std.range;

void main()
{
    auto t = [ tuple(1.5, 100), tuple(2.5, 200) ];

    foreach (a, b; t.retro) {
        writefln("%s, %s", a, b);
    }
}

Because t.retro is a range, the foreach extracts the members of the tuple and we get the folloing output:

2.5, 200
1.5, 100

Now, remove the .retro part; the range becomes a slice, in which case 'a' becomes the iteration counter and 'b' becomes the tuple value:

0, Tuple!(double, int)(1.5, 100)
1, Tuple!(double, int)(2.5, 200)

Is that a WAT? :)

Ali

August 23, 2014
On Saturday, 23 August 2014 at 20:34:35 UTC, Ali Çehreli wrote:
> There are a number of inconsistencies around tuples. The behavior you expect is present for ranges that return tuple fronts:
>
> import std.stdio;
> import std.typecons;
> import std.range;
>
> void main()
> {
>     auto t = [ tuple(1.5, 100), tuple(2.5, 200) ];
>
>     foreach (a, b; t.retro) {
>         writefln("%s, %s", a, b);
>     }
> }
>
> Because t.retro is a range, the foreach extracts the members of the tuple and we get the folloing output:
>
> 2.5, 200
> 1.5, 100
>
> Now, remove the .retro part; the range becomes a slice, in which case 'a' becomes the iteration counter and 'b' becomes the tuple value:
>
> 0, Tuple!(double, int)(1.5, 100)
> 1, Tuple!(double, int)(2.5, 200)
>
> Is that a WAT? :)
>
> Ali

I cannot wait until we get proper tuple destructuring and this buggy foreach unpacking dies.