Bug 3123 – std.algorithm.zip fails on 'lazy' ranges

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
Other
OS
All
Creation time
2009-07-01T12:16:00Z
Last change time
2015-06-09T01:27:56Z
Keywords
rejects-valid
Assigned to
andrei
Creator
k-foley

Attachments

IDFilenameSummaryContent-TypeSize
481zippy.dZip fixestext/x-dsrc6974

Comments

Comment #0 by k-foley — 2009-07-01T12:16:54Z
By 'lazy' range, I mean what iota, map, take, etc. return. I don't know the correct term for these types of ranges. ---- auto a = [1, 2, 3, 4, 5][]; auto b = [2, 4, 6, 8, 10][]; // this compiles and works fine foreach ( e; zip(a, b) ) writeln( "(", e.at!0, ", ", e.at!1, ")" ); // the following do not foreach ( e; zip(a, iota(0, 6)) ) writeln( "(", e.at!0, ", ", e.at!1, ")" ); foreach ( e; zip(a, take(5, repeat(42))) ) writeln( "(", e.at!0, ", ", e.at!1, ")" ); foreach ( e; zip(a, map!(`a*a`)(a)) ) writeln( "(", e.at!0, ", ", e.at!1, ")" ); ---- Here is the compilation error: C:\d\dmd.2.030\dmd\windows\bin\..\..\src\phobos\std\range.d(1734): Error: cannot implicitly convert expression (&this.ranges._field_field_1.front) of type int d elegate() to int*
Comment #1 by dsimcha — 2009-10-25T15:30:37Z
The problem looks to be a question of whether range.front is an lvalue or not. When range.front is an lvalue, DMD interprets &range.front as taking the address of the front element of the range. When range.front is not an lvalue, DMD interprets &range.front as taking the address of the member function front() of range.
Comment #2 by k-foley — 2009-10-25T21:08:42Z
Created attachment 481 Zip fixes
Comment #3 by k-foley — 2009-10-25T21:10:50Z
(In reply to comment #1) > The problem looks to be a question of whether range.front is an lvalue or not. > When range.front is an lvalue, DMD interprets &range.front as taking the > address of the front element of the range. When range.front is not an lvalue, > DMD interprets &range.front as taking the address of the member function > front() of range. The problem is that Proxy tries to store a pointer to the fronts of each range. In the case of these 'lazy' ranges, the pointer makes no sense. I have uploaded a new version of Zip which I think solves this problem.
Comment #4 by k-foley — 2009-10-25T21:13:39Z
(In reply to comment #2) > Created an attachment (id=481) [details] > Zip fixes I changed Proxy to store by reference for ranges supporting reference return types and by value otherwise. I also changed Zip to only support back and popBack when all ranges are bidirectional. And I also changed Proxy.at to return by reference.
Comment #5 by dsimcha — 2010-08-15T19:55:27Z
Fixed SVN.