Thread overview
Formatted output of range of tuples
Oct 08, 2014
antropod
Oct 08, 2014
bearophile
Oct 13, 2014
Ali Çehreli
Oct 13, 2014
bearophile
Oct 08, 2014
anonymous
Oct 08, 2014
Ali Çehreli
Oct 08, 2014
antropod
Oct 08, 2014
bearophile
Oct 13, 2014
monarch_dodra
Oct 13, 2014
Sag Academy
October 08, 2014
Hello!

Consider this code:

+++
import std.stdio;
import std.range;
import std.algorithm;

void printIndexedArray1(T, Range)(T[] source, Range indexes)
{
	foreach(row; zip(indexes, source))
	{
		foreach(col; row) {
			write(col, " ");
		}
		writeln;
	}
}

void printIndexedArray2(T, Range)(T[] source, Range indexes)
{
	writef("%(%(%s %)\n%)", zip(indexes, source));
}

void main()
{
	uint[] data = [17, 30, 48, 140, 10, 01, 126, 138, 140, 3, 501];
	printIndexedArray1(data, sequence!"n");
	printIndexedArray2(data, sequence!"n");

}
+++

Looks fairly straightforward. But, the second function causes compilation error:

std.format.FormatException@C:\D\dmd2\windows\bin\..\..\src\phobos\std\format.d(2
585): Expected '%s' format specifier for type 'Tuple!(uint, uint)'

Can you help me with that?
October 08, 2014
antropod:

> Looks fairly straightforward. But, the second function causes compilation error:
>
> std.format.FormatException@C:\D\dmd2\windows\bin\..\..\src\phobos\std\format.d(2
> 585): Expected '%s' format specifier for type 'Tuple!(uint, uint)'
>
> Can you help me with that?

Currently the "%(%s%)" formatting doesn't support tuples as sequences of values.

For indexes now there is also "enumerate".

Bye,
bearophile
October 08, 2014
On Wednesday, 8 October 2014 at 21:21:47 UTC, antropod wrote:
> Hello!
>
> Consider this code:
>
> +++
> import std.stdio;
> import std.range;
> import std.algorithm;
>
> void printIndexedArray1(T, Range)(T[] source, Range indexes)
> {
> 	foreach(row; zip(indexes, source))
> 	{
> 		foreach(col; row) {
> 			write(col, " ");
> 		}
> 		writeln;
> 	}
> }
>
> void printIndexedArray2(T, Range)(T[] source, Range indexes)
> {
> 	writef("%(%(%s %)\n%)", zip(indexes, source));
> }
>
> void main()
> {
> 	uint[] data = [17, 30, 48, 140, 10, 01, 126, 138, 140, 3, 501];
> 	printIndexedArray1(data, sequence!"n");
> 	printIndexedArray2(data, sequence!"n");
>
> }
> +++
>
> Looks fairly straightforward. But, the second function causes compilation error:
>
> std.format.FormatException@C:\D\dmd2\windows\bin\..\..\src\phobos\std\format.d(2
> 585): Expected '%s' format specifier for type 'Tuple!(uint, uint)'
>
> Can you help me with that?

You can turn the tuples into ranges with `only`:

writef("%(%(%s %)\n%)", zip(indexes, source).map!(t =>
only(t.expand)));
October 08, 2014
On 10/08/2014 02:34 PM, anonymous wrote:

> You can turn the tuples into ranges with `only`:
>
> writef("%(%(%s %)\n%)", zip(indexes, source).map!(t =>
> only(t.expand)));

I haven't measured the performance but there is also the following automatic expansion of tuple members as slice elements:

    ... zip(indexes, source).map!(t => [ t ]));

Probably the same thing...

Ali

October 08, 2014
On Wednesday, 8 October 2014 at 21:34:54 UTC, anonymous wrote:
>
> You can turn the tuples into ranges with `only`:
>
> writef("%(%(%s %)\n%)", zip(indexes, source).map!(t =>
> only(t.expand)));

That works for me, thanks.

By the way my compiler is DMD 2.066.0
October 08, 2014
anonymous:

> You can turn the tuples into ranges with `only`:
>
> writef("%(%(%s %)\n%)", zip(indexes, source).map!(t => only(t.expand)));

This is a nice idea. Expand can probably be replaced by a []. I presume this works only if the types inside the tuple are the same.

Bye,
bearophile
October 13, 2014
On 10/08/2014 02:31 PM, bearophile wrote:

> For indexes now there is also "enumerate".
>
> Bye,
> bearophile

Thanks for the tip. std.range.enumerate makes a big difference:

    foreach (i, element; MyRange(42).enumerate) {
        // ...
    }

versus sequence!"n" and zip:

    foreach (i, element; zip(sequence!"n", MyRange(42))) {
        // ...
    }

Ali

October 13, 2014
Ali Çehreli:

>     foreach (i, element; MyRange(42).enumerate) {
>         // ...
>     }
>
> versus sequence!"n" and zip:
>
>     foreach (i, element; zip(sequence!"n", MyRange(42))) {
>         // ...
>     }

But it's better to not use automatic unpacking of tuples. See issues 7361 and especially 9817.

Bye,
bearophile
October 13, 2014
On Wednesday, 8 October 2014 at 23:28:34 UTC, bearophile wrote:
> anonymous:
>
>> You can turn the tuples into ranges with `only`:
>>
>> writef("%(%(%s %)\n%)", zip(indexes, source).map!(t => only(t.expand)));
>
> This is a nice idea. Expand can probably be replaced by a []. I presume this works only if the types inside the tuple are the same.

Expand creates "returns" a TypeTuple though, so it's arguably "free". "[]" allocates a dynamic array, so is costly.

On the flip side, "only" is *entirelly* by value, and carries all its arguments. If the tuple is big, then the range can become quite big.
October 13, 2014
On Monday, 13 October 2014 at 09:20:27 UTC, monarch_dodra wrote:
> On Wednesday, 8 October 2014 at 23:28:34 UTC, bearophile wrote:
>> anonymous:
>>
>>> You can turn the tuples into ranges with `only`:
>>>
>>> writef("%(%(%s %)\n%)", zip(indexes, source).map!(t => only(t.expand)));
>>
>> This is a nice idea. Expand can probably be replaced by a []. I presume this works only if the types inside the tuple are the same.
>
> Expand creates "returns" a TypeTuple though, so it's arguably "free". "[]" allocates a dynamic array, so is costly.
>
> On the flip side, "only" is *entirelly* by value, and carries all its arguments. If the tuple is big, then the range can become quite big.

> you are right man.