On 11/17/17 8:13 AM, Adam D. Ruppe wrote:
On Friday, 17 November 2017 at 06:57:16 UTC, Michael V. Franklin wrote:
Actually, it looks like it's this 4-year old bug.
https://issues.dlang.org/show_bug.cgi?id=9506
Yeah, I suspected this is old and my comment in there still applies...
It passes the isInputRange test due to the implicit conversion of alias
this, and then writeln takes it and consumes it.
In doing some digging, I found that it actually calls the object version
of formatValue. Which is specifically written to check if
Object.toString has been overridden. If not, and it has a range
interface, it treats it as a range.
So this is not a bug. By using alias this against a range, you have
turned it into a range interface.
One thing you might consider is making the alias this go to a getter
property instead of the method directly. Then operations on it will work
on a copy of the slice, and thus not consume the original one. But then
you can't do stuff like append do it directly either...
It doesn't work, I tried that. The reason is because, for arrays,
popFront requires an lvalue (obviously), and so isInputRange for such a
class is false.
It just prints the class name, like a normal class.
Ironically, alias this to a struct range type (like say filter), would
be even more disastrous:
class C(R)
{
R foo;
R getFoo() { return foo; }
alias getFoo this;
}
auto f = [1, 2, 3, 4].filter!"a & 1";
auto c = new C!(typeof(f));
c.foo = f;
writeln(c);// [1, 1, 1, 1, 1, 1,....
This is because C.getFoo.popFront works, even though it's an rvalue!
I don't think there's a way to figure out this situation and properly
deal with it. My recommendation is basically, don't do this. It's not
going to work like you expect.
imo writeln should check for .save and use it. But meh I don't care to
personally bother fixing it and apparently nobody else does either.
.save isn't even properly implemented. It must return the same type as
the original.
e.g.: static assert(!isForwardRange!C);
Jonathan has talked about this, and I agree with him. The only real way
to fix forward ranges is to get rid of save, and make copyability the
thing that makes a forward range a forward range. But that's not going
to happen, too disruptive.
-Steve