writeln, alias this and dynamic arrays.
Steven Schveighoffer
schveiguy at yahoo.com
Fri Nov 17 14:28:54 UTC 2017
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
More information about the Digitalmars-d-learn
mailing list