Bug 9817 – Syntax change for front tuple expansion in foreach

Status
RESOLVED
Resolution
WONTFIX
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-03-26T06:04:00Z
Last change time
2017-06-13T21:33:26Z
Assigned to
nobody
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2013-03-26T06:04:17Z
I have tagged this as bug report instead of as enhancement request. This program shows that D foreach is able to "unpack" tuples that are produced by a range: import std.algorithm: group; void main() { auto data = ['a', 'a', 'b', 'b']; foreach (c, n; group(data)) { pragma(msg, typeof(c)); pragma(msg, typeof(n)); } } It prints: dchar uint This feature is mostly undocumented: http://d.puremagic.com/issues/show_bug.cgi?id=7361 But this feature doesn't work with an array of tuples (because it clashes against a precedent semantics of foreach, that assigns the first variable to the indexes of the array): import std.typecons: tuple; void main() { auto data = [tuple("red", 10), tuple("blue", 20)]; foreach (x, y; data) { pragma(msg, typeof(x)); pragma(msg, typeof(y)); } } It prints: uint Tuple!(string, int) In this thread (and on Bugzilla) I have suggested to add unpacking syntax in various situations: http://forum.dlang.org/post/[email protected] I think the fully transparent unpacking syntax as in "foreach(c,n; group(data))" is rigid (there is no way to tell if you want the first variable to be bound to the array index, or to the first item of the tuple) and not sufficiently explicit. So I propose to replace the current syntax that unpacks tuples with a different and explicit syntax that removed ambiguities, is more flexible, and works with both arrays and ranges: import std.algorithm: group; import std.typecons: tuple; void main() { auto data1 = ['a', 'a', 'b', 'b']; foreach ((c, n); group(data1)) {} auto data2 = [tuple("red", 10), tuple("blue", 20)]; foreach ((s, n); data2) {} foreach (i, tup; data2) {} foreach (i, (s, n); data2) {} } This syntax is meant to be usable in other situations, so it must be designed thinking about the future too: import std.typecons: tuple; void foo((string s, int b)) {} void main() { foo(tuple("red", 10)); auto (a, b) = tuple("red", 10); auto t = tuple("red", 10); switch (t) { case (a, b): break; default: } } Other syntaxes are possible.
Comment #1 by bearophile_hugs — 2014-10-11T11:23:52Z
The idea is to deprecate and then remove the current syntax (that is undocumented, see Issue 7361 ) and to replace it with a general syntax to unpack tuples.
Comment #2 by schveiguy — 2017-06-13T21:33:26Z
This is a feature of foreach on ranges, not arrays. Arrays are arrays first, and ranges second. It's the reason foreach(c; "string") doesn't iterate dchars by default, and the reason foreach(dchar d; "string") works, but foreach(dchar d; someCharRange) does not. I think you are talking about two different things here. While I agree that foreach being able to use tuples to unpack in the syntax you propose would be nice, I don't think it hurts to omit the parentheses. Unpacking tuples syntax can exist alongside the existing mechanism. In any case, the mechanism is too far ingrained into the language to be simply deprecated. We can revisit at a later date if/when tuple unpacking becomes possible.