Bug with writeln?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Sep 6 16:55:17 UTC 2018


On Thursday, September 6, 2018 2:40:08 AM MDT Saurabh Das via Digitalmars-d-
learn wrote:
> Is this a bug with writeln?
>
> void main()
> {
>      import std.stdio, std.range, std.algorithm;
>
>      auto a1 = sort([1,3,5,4,2]);
>      auto a2 = sort([9,8,9]);
>      auto a3 = sort([5,4,5,4]);
>
>      pragma(msg, typeof(a1));
>      pragma(msg, typeof(a2));
>      pragma(msg, typeof(a3));
>
>      auto b = [a1, a2, a3];
>      pragma(msg, typeof(b));
>
>      writeln("b:");
>      writeln(b);
>      writeln(b);  // <-- this one prints incorrectly
>
>      writeln("a:");
>      writeln(a1);
>      writeln(a2);
>      writeln(a3);
>
> }
>
> Output
> ======
>
> SortedRange!(int[], "a < b")
> SortedRange!(int[], "a < b")
> SortedRange!(int[], "a < b")
> SortedRange!(int[], "a < b")[]
> b:
> [[1, 2, 3, 4, 5], [8, 9, 9], [4, 4, 5, 5]]
> [[], [], []]
> a:
> [1, 2, 3, 4, 5]
> [8, 9, 9]
> [4, 4, 5, 5]
>
> The issue goes away if I cast 'b' to const before writeln. I
> think it is a bug, but maybe I am missing something?

It's not a bug in writeln. Any time that a range is copied, you must not do
_anything_ else with the original unless copying it is equivalent to calling
save on it, because the semantics of copying a range are unspecified. They
vary wildly depending on the range type (e.g. copying a dynamic array is
equivalent to calling save, but copying a class reference is not). When you
pass the range to writeln, you must assumed that it may have been consumed.
And since you have range of ranges, you must assume that the ranges that are
contained may have been consumed. If you want to pass them to writeln and
then do anything else with them, then you'll need to call save on every
range involved (which is a bit of a pain with a range of ranges, but it's
necessary all the same).

In many cases, you can get away with passing a range to a function or use it
with foreach and then continue to use it after that, but that's only because
copying those ranges is equivalent to calling save on them. It doesn't work
if any of the ranges involved aren't saved when they're copied, and it
doesn't work in generic code, because you have no clue whether the ranges
that are going to be used with that code are going to be saved when they're
copied.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list