Bug 7924 – reduce does not work with immutable/const as map and filter do

Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-04-16T08:23:00Z
Last change time
2014-02-25T12:23:48Z
Assigned to
nobody
Creator
russel

Comments

Comment #0 by russel — 2012-04-16T08:23:47Z
(I have marked this as x86_64/Linux as that is the only platform I have tried this on. I am fairly convinced it is an all/all though.) The following code: import std.algorithm ; import std.range ; import std.stdio ; void main ( immutable string[] args ) { immutable r = iota ( 0 , 10 ) ; writeln ( map ! ( i => i * i ) ( r ) ) ; writeln ( filter ! ( i => true ) ( r ) ) ; writeln ( reduce ! ( ( a , b ) => a + b ) ( 10 , r ) ) ; } fails to compile using DMD 2.059 with the message: /home/users/russel/lib.Linux.x86_64/DMD2/bin64/../../src/phobos/std/algorithm.d(725): Error: function std.range.iota!(int,int).iota.Result.popFront () is not callable using argument types () /home/users/russel/lib.Linux.x86_64/DMD2/bin64/../../src/phobos/std/algorithm.d(725): Error: function std.range.iota!(int,int).iota.Result.front () is not callable using argument types () issue_XXXX.d(9): Error: template instance issue_XXXX.main.reduce!(__lambda7).reduce!(int,immutable(Result)) error instantiating Failed: 'dmd' '-v' '-o-' 'issue_XXXX.d' '-I.' If the immutable is replaced with const the same message ensues with s/immutable/const/. If the reduce is commented out then it all works: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] reduce is thus not consistent with map and filter, which I think has to be considered a serious error.
Comment #1 by irritate — 2013-06-19T20:17:02Z
The error message on head revision (DMD 2.064) is different, but this still fails to compile. The problem here is that reduce() fails to instantiate because of an isIterable constraint check on the immutable iota. I "unwound" the example into just the iteration: --- import std.stdio ; void main() { immutable r = iota(0, 10); foreach(elem; r) { writeln(elem); } } DMD v2.064 DEBUG issue_7924.d(8): Error: mutable method std.range.iota!(int, int).iota.Result.popFront is not callable using a immutable object --- And popFront mutates a member variable for the current value, so I don't think there's much we can do about this. SIDE NOTE: map and filter work because they Unqual the iota when they wrap it. However they also have non-const popFront, and making them immutable directly also leads to issues because of that: --- import std.stdio ; void main() { immutable r = map!(i => i*i)(iota(0, 10)); foreach(elem; r) { writeln(elem); } } DMD v2.064 DEBUG issue_7924.d(7): Error: cannot implicitly convert expression (map(iota(0, 10)) of type MapResult!(__lambda2, Result) to immutable(MapResult!(__lambda2, Result) ) ---
Comment #2 by monarchdodra — 2014-02-25T12:23:48Z
immutable(Iota) is not a range => Requirements are that the argument is a range. The fact that map and filter accept const ranges is wrong to begin with. There are cases where it is possible to strip the constness, but this is not always the case. Doing a "dumb cast" could have some potentially crash-inducing consequences. It would be better to have a generic solution to this problem, instead of hacking at it again and again in every implementations. So for now, let's just leave this at "Not a range, sorry".