June 26, 2022

On 6/25/22 7:44 PM, WebFreak001 wrote:

>

let's see this code:

import std.range;

int[] arr;
arr.put(2);

someone not coming from a D backround (or even those coming from it) might expect here to have arr be equal to [2] afterwards.

However this is not the case:

core.exception.AssertError@/dlang/dmd/linux/bin64/../../src/phobos/std/range/primitives.d(2472): Attempting to fetch the front of an empty array of int
----------------
??:? _d_assert_msg [0x563cbe9c3360]
/dlang/dmd/linux/bin64/../../src/phobos/std/range/primitives.d:2472 pure nothrow ref @property @nogc @safe inout(int) std.range.primitives.front!(int).front(return scope inout(int)[]) [0x563cbe9a0fe3]
/dlang/dmd/linux/bin64/../../src/phobos/std/range/primitives.d:297 pure nothrow @nogc @safe void std.range.primitives.doPut!(int[], int).doPut(ref int[], ref int) [0x563cbe9a0f62]
/dlang/dmd/linux/bin64/../../src/phobos/std/range/primitives.d:380 pure nothrow @nogc @safe void std.range.primitives.put!(int[], int).put(ref int[], int) [0x563cbe9a0f37]
./onlineapp.d:8 _Dmain [0x563cbe9a0ee1]

this is because put is there to write into a pre-allocated buffer if you pass in an array, as it assumes it is a slice:

int[3] buffer;
auto slice = buffer[];
put(slice, 1);
put(slice, 2);
put(slice, 3);
assert(!slice.length);
assert(buffer == [1,2,3]);

which seems to be the way this is intended to be used.

However now I argue this is very unintuitive behavior, especially when you compare it to appender!int:

auto arr = appender!(int[]);
arr.put(1);
assert(arr.data == [1]);

put on an appender actually adds to the array, the appender allocates memory for it.

I strongly feel that this behavior is very inconsistent and unexpected for most users and should be changed. I think we should deprecate simple arrays/slices on put and rename the method for those.

I propose put with slices should be renamed to putInto.

It might not be expected, but to disable allowing reference input ranges as output ranges would break so many fundamental usages, such as std.algorithm.copy. You wouldn't just be disabling slices, it would be a complete removal of a whole class of output ranges.

What we need is an appendTo wrapper:

struct AppendTo(T)
{
   private T[] *arr;
   this(return T[]* arr) { this.arr = arr; }
   void put(X)(X val) if (__traits(compiles, (*arr) ~= val)) {
      (*arr) ~= val;
   }
}

auto appendTo(T)(return ref T[] arr)
{
   return AppendTo!T(&arr);
}

-Steve

June 26, 2022

On 6/26/22 6:29 AM, H. S. Teoh wrote:

>

On Sun, Jun 26, 2022 at 06:33:13AM +0000, Kostiantyn Tokar via Digitalmars-d wrote:
[...]

>

What should I do if I want to preallocate a slice and copy some input range
into it? I wouldn't be able to use std.algorithm.copy for this simple
purpose, because it uses put internally.

Just take a slice of it with [].

Taking a slice of a slice does nothing.

-Steve

June 26, 2022
On Sunday, 26 June 2022 at 12:35:10 UTC, Paul Backus wrote:
> On Sunday, 26 June 2022 at 05:10:50 UTC, H. S. Teoh wrote:
>> On Sun, Jun 26, 2022 at 04:21:46AM +0000, Paul Backus via Digitalmars-d wrote:
>>> IMO `put` should be changed in `std.v2` to either throw an exception or return `false` when attempting to insert an element into a full output range.
>>
>> Why the needlessly complex workaround? Just introduce a .full method, the natural analogue of .empty for output ranges.
>
> How would you implement .full for, say, an output range that writes to a file?

Yes, or a concurrent one.
June 26, 2022

On Sunday, 26 June 2022 at 10:58:48 UTC, Kostiantyn Tokar wrote:

>

On Sunday, 26 June 2022 at 10:29:17 UTC, H. S. Teoh wrote:

>

On Sun, Jun 26, 2022 at 06:33:13AM +0000, Kostiantyn Tokar via Digitalmars-d wrote: [...]

>

What should I do if I want to preallocate a slice and copy some input range into it? I wouldn't be able to use std.algorithm.copy for this simple purpose, because it uses put internally.

Just take a slice of it with [].

T

I'm talking about suggestion. IIUC, with suggested change put will be appending to the slice. And it wouldn't work with @nogc.

no, the suggestion is only to deprecate the put for slices and disallow it completely with that function name, to avoid errors in code bases.

Appending to the slice would not work because of the @nogc change and also because it's a backwards-incompatible breaking change.

1 2
Next ›   Last »