D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 5489 - std.typecons tuples dynamically iterable
Summary: std.typecons tuples dynamically iterable
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: All All
: P2 enhancement
Assignee: Seb
URL:
Keywords: pull
Depends on:
Blocks:
 
Reported: 2011-01-26 04:52 UTC by bearophile_hugs
Modified: 2017-12-21 21:39 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description bearophile_hugs 2011-01-26 04:52:23 UTC
std.typecons tuples are not arrays, and their items don't need to be all of the same type. But in Python programming with tuples I have seen that once in a while it's useful to iterate on their items.

Currently in D2 (DMD 2.051) you are allowed to iterate on tuple items, but this is a "static foreach":

import std.stdio, std.typecons;
void main() {
    auto t = tuple(1, 2, 3, 4);
    /*static*/ foreach (x; t.tupleof)
        writeln(x);
}


This is dynamic:

import std.typecons, std.algorithm;
void main() {
    auto t = tuple(1, 2, 3, 4);
    auto total = reduce!q{a + b}([t.tupleof]);
    assert(total == 10);
}


But in some situations with usage of zip and other things it's not handy to convert tuples in arrays in that way. So I'd like tuples made of the same type of items (castable) to be iterable (a "static if" disables the range protocol methods if std.traits.CommonType applied on the tuple items is void):

import std.typecons, std.algorithm;
void main() {
    auto t = tuple(1, 2, 3, 4);
    auto total = reduce!q{a + b}(t);
    assert(total == 10);
}


With sum() from bug 4725 it becomes:

import std.typecons, std.algorithm;
void main() {
    auto t = tuple(1, 2, 3, 4);
    auto total = reduce!sum(t);
    assert(total == 10);
}


Another hypotetical example usage:

import std.typecons, std.algorithm, std.range;
void main() {
    auto t1 = tuple(1, 2, 3, 4);
    auto t2 = tuple(10, 20, 30, 40);
    auto r = map!sum(zip(t1, t2));
    assert(r == [11, 22, 33, 44]);
}


Equivalent Python2 working code:

>>> t1 = (1, 2, 3, 4)
>>> t2 = (10, 20, 30, 40)
>>> map(sum, zip(t1, t2))
[11, 22, 33, 44]
Comment 1 Neia Neutuladh 2017-12-04 23:02:31 UTC
I just came across an instance of this:

        cartesianProduct(
                ["%a, ", "%A, ", ""],
                ["%d "],
                ["%b", "%B"],
                [" %Y %H:%M:%S "],
                ["%Z", "%z", "%.%.%.", "%.%.", "%."]
                )
        .map!(x => joiner(x, "").array.to!string)
        .array

I ended up using [x.tupleof], but it didn't occur to me that that was possible. I only found out about that by looking at this issue.
Comment 2 Seb 2017-12-21 14:27:55 UTC
This already works if you combine .expand with std.range.only:

```
import std.algorithm, std.range, std.stdio, std.typecons;
auto t = tuple(1, 2);
t.expand.only.sum.writeln;
```

PR to add this as an example: https://github.com/dlang/phobos/pull/5953
Comment 3 github-bugzilla 2017-12-21 21:39:52 UTC
Commits pushed to master at https://github.com/dlang/phobos

https://github.com/dlang/phobos/commit/059be4da3afe87bff6c8c37186c8fdef271f3388
Fix Issue 5489 - std.typecons tuples dynamically iterable

https://github.com/dlang/phobos/commit/0ba08bb6530ce84709f141645e2f6f28ab551813
Merge pull request #5953 from wilzbach/fix-5489

Fix Issue 5489 - std.typecons tuples dynamically iterable
merged-on-behalf-of: MetaLang <MetaLang@users.noreply.github.com>