Bug 4347 – foreach over range should save range.

Status
RESOLVED
Resolution
WONTFIX
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2010-06-19T08:49:00Z
Last change time
2016-12-22T15:05:01Z
Assigned to
andrei
Creator
dsimcha

Comments

Comment #0 by dsimcha — 2010-06-19T08:49:42Z
To be consistent with the old definition of forward ranges, and with arrays and opApply-based ranges, a foreach loop should call save() if it's available. The example below demonstrates why not doing so is problematic. import std.stdio; class SomeRange { uint num; uint front() { return num; } void popFront() { num++; } bool empty() @property { return num >= 10; } typeof(this) save() @property { auto ret = new typeof(this); ret.num = num; return ret; } } void main() { auto r = new SomeRange; foreach(elem; r) { writeln(elem); // Prints numbers 0-9. } foreach(elem; r) { writeln(elem); // Nothing. } }
Comment #1 by torarind — 2011-05-05T18:47:16Z
I think save() should be required, since the semantics of foreach when iterating over arrays imply a save() on the array. Letting forward range behaviour depend on whether the range is a class or a struct is bound to be confusing.
Comment #2 by monarchdodra — 2014-06-12T20:02:18Z
I disagree with this. saving a range should always be the caller's responsibility/choice. If the argument "people expect the range to be saved" prevails here, it means "save" is failed as a concept, and forward ranges should simply be defined as "ranges that implicitly save on copy": EG no need for save, only for a postblit that's *always* called.
Comment #3 by andrei — 2016-12-22T14:35:53Z
I'll close this because addressing it may disrupt code. Also it would make behavior of foreach different across input and other ranges.
Comment #4 by mathias.lang — 2016-12-22T14:56:45Z
@Andrei: Actually, there is already a difference in behavior. When iterating over a range which is a reference (e.g. class), the range will be advanced by foreach. However, for value types (structs), the struct is copied, resulting in an implict `.save` most of the time. See https://issues.dlang.org/show_bug.cgi?id=15413 for example.
Comment #5 by andrei — 2016-12-22T15:05:01Z
(In reply to Mathias Lang from comment #4) > @Andrei: Actually, there is already a difference in behavior. When iterating > over a range which is a reference (e.g. class), the range will be advanced > by foreach. > However, for value types (structs), the struct is copied, resulting in an > implict `.save` most of the time. > See https://issues.dlang.org/show_bug.cgi?id=15413 for example. I understand that. Still think we should not change behavior.