Scope Containers

Atila Neves atila.neves at gmail.com
Mon Mar 11 18:29:23 UTC 2019


On Monday, 11 March 2019 at 17:00:35 UTC, bitwise wrote:
> On Sunday, 10 March 2019 at 18:46:14 UTC, Atila Neves wrote:
>> On Sunday, 10 March 2019 at 17:36:09 UTC, bitwise wrote:
>>> On Sunday, 10 March 2019 at 16:10:10 UTC, Atila Neves wrote:
>>>> On Sunday, 10 March 2019 at 15:12:03 UTC, bitwise wrote:
>>>>> [...]
>>>>
>>>> Like `const`, `scope` on a member function means that the 
>>>> `this` reference is `scope`.
>>>
>>> Interesting. I'll have to look up some examples.
>>>
>>>>> [...]
>>>>
>>>> https://github.com/atilaneves/automem/blob/2a97acba94d6fe0bf9ba07fec99e86e46aa0f2a1/source/automem/vector.d#L134
>>>> https://github.com/atilaneves/automem/blob/2a97acba94d6fe0bf9ba07fec99e86e46aa0f2a1/source/automem/vector.d#L159
>>>> https://github.com/atilaneves/automem/blob/2a97acba94d6fe0bf9ba07fec99e86e46aa0f2a1/source/automem/vector.d#L145
>>>>
>>>> static assert(isInputRange!(Vector!int));
>>>>
>>>>> [...]
>>>>
>>>> I would think so, especially since I wrote Vector to be 
>>>> @safe with dip1000. Look at this unit test for not being 
>>>> able to escape the payload for example:
>>>>
>>>> https://github.com/atilaneves/automem/blob/master/tests/ut/vector.d#L229
>>>
>>> Ok, but this container copies the entire collection in 
>>> postblit:
>>> https://github.com/atilaneves/automem/blob/2a97acba94d6fe0bf9ba07fec99e86e46aa0f2a1/source/automem/vector.d#L104
>>
>> Well, yes. As it says in the module ddoc, it's my version of 
>> C++'s std::vector. If you don't want it to copy, pass by ref.
>>
>>> So if you try to treat it like a range, you'll take a 
>>> performance hit every time you trigger the postblit, which 
>>> seems likely.
>>
>> You can pass it by ref like I mention above, or you could 
>> slice it and pass the slice instead. Without DIP1000 passing 
>> the slice wouldn't be @safe but with it, it is.
>>
>> Again, just like std::vector, which is pretty much always 
>> passed by const ref. But safer and with a default allocator.
>>
>>> Isn't it reasonable to assume a range should act like a 
>>> reference to data, rather than a copy of it?
>>
>> It depends.
>
> This container seems good for short-lived usage.

Why?

> If I wanted to pass a bunch of filenames to a function for 
> processing, I would consider this container Ok, because it 
> would allocate once, then be consumed as a range without having 
> to copy anything.

Or you don't consume it all and slice it (as I mentioned in my 
last post):

@safe unittest {
     scope v = vector(1, 2, 3);
     static void fun(R)(R range) {
         import std.array: array;
         assert(range.array == [1, 2, 3]);
     }
     fun(v[]);
     // wasn't consumed
     assert(v[] == [1, 2, 3]);
}

Again, it's @safe because the slice is scoped.

> For any kind of persistent storage though, I would consider the 
> performance costs of using this container's range functionality 
> too high.

There aren't any performance costs. You pass a fat pointer just 
like you would with a GC array.

> I do think the idea of making the container itself the range is 
> interesting, but what ruins it for me is the fact that ranges 
> are consumable.

Which is why Vector has both opSlice and copies by default. It's 
only a range itself if the element type is mutable, otherwise it 
doesn't even define popFront.

> So I'm wondering if it would work well to use an integer index 
> for the range implementation

That's what slices are.




More information about the Digitalmars-d mailing list