Thread overview
Explicit Slicing of std.container.Array
Jan 24, 2015
Nordlöw
Jan 24, 2015
Tobias Pankrath
Jan 24, 2015
Nordlöw
Jan 24, 2015
ketmar
Jan 24, 2015
Nordlöw
Jan 24, 2015
Laeeth Isharc
Jan 24, 2015
Nordlöw
Jan 25, 2015
Jonathan M Davis
January 24, 2015
Is there a reason why std.container.Array have to be explicitly sliced before being processed by range algorithms such as filter typically as

    import std.container: Array;
    Array!int a;
    foreach (e; a[].filter!"true") {}

?

Does memory allocation play a role?

I would like to see it be used in replace of D builtin arrays without any code changes.
January 24, 2015
On Saturday, 24 January 2015 at 13:11:33 UTC, Nordlöw wrote:
> Is there a reason why std.container.Array have to be explicitly sliced before being processed by range algorithms such as filter typically as
>
>     import std.container: Array;
>     Array!int a;
>     foreach (e; a[].filter!"true") {}
>
> ?
>
> Does memory allocation play a role?
>
> I would like to see it be used in replace of D builtin arrays without any code changes.

Because container are no ranges. If they were ranges, what would array.popFront() do?
January 24, 2015
On Saturday, 24 January 2015 at 13:11:33 UTC, Nordlöw wrote:
> Is there a reason why std.container.Array have to be explicitly sliced before being processed by range algorithms such as filter typically as
>
>     import std.container: Array;
>     Array!int a;
>     foreach (e; a[].filter!"true") {}
>
> ?
>
> Does memory allocation play a role?
>
> I would like to see it be used in replace of D builtin arrays without any code changes.

One thing to mention in the revised docs in the introduction to std.algorithms.
January 24, 2015
On Saturday, 24 January 2015 at 15:30:36 UTC, Laeeth Isharc wrote:
> One thing to mention in the revised docs in the introduction to std.algorithms.

https://github.com/D-Programming-Language/phobos/pull/2904

Thanks!
January 24, 2015
On Saturday, 24 January 2015 at 13:59:13 UTC, Tobias Pankrath wrote:
>>    foreach (e; a[].filter!"true") {}

Is a[] a no-op if a is a D normal builtin array/slice?
January 24, 2015
On Sat, 24 Jan 2015 19:51:30 +0000, Nordlöw wrote:

> On Saturday, 24 January 2015 at 13:59:13 UTC, Tobias Pankrath wrote:
>>>    foreach (e; a[].filter!"true") {}
> 
> Is a[] a no-op if a is a D normal builtin array/slice?

yes. the following source produces the same machine code regardless of slicing on `z` with 'dmd -c':

  usize test (int[] a) { return a.length; }

  int main () {
    int[] z = new int[](4);
    z[0] = 42;
    z[3] = 666;
    return test(z[]);
  }


January 24, 2015
On Saturday, 24 January 2015 at 21:10:29 UTC, ketmar wrote:
> yes. the following source produces the same machine code regardless of
> slicing on `z` with 'dmd -c':

Nice, that's what I had hoped for! Thanks.
January 25, 2015
On Saturday, January 24, 2015 13:11:31 Nordlöw via Digitalmars-d-learn wrote:
> Is there a reason why std.container.Array have to be explicitly sliced before being processed by range algorithms such as filter typically as
>
>      import std.container: Array;
>      Array!int a;
>      foreach (e; a[].filter!"true") {}
>
> ?
>
> Does memory allocation play a role?
>
> I would like to see it be used in replace of D builtin arrays without any code changes.

Dynamic arrays are an odd beast in that they're sort of containers and sort of not, because they don't really manage their own memory. Either they're a slice of the stack, manually managed memory, or from GC-allocated memory. So, really, it's what they're a slice of that manages the memory. And when you do stuff like ~=, then GC is what takes care of it (possibly reallocating the memory as GC-allocated memory even if it referred to manually-allocated memory before). But the dynamic array itself does not. It doesn't manage memory any more than a pointer does. Just like incrementing a pointer doesn't involve managing memory, calling popFront on an dynamic array doesn't manage memory. It just changes exactly which piece of memory you're looking at. So, a dynamic array can function as a range.

In contrast, an actual container like std.container.Array _does_ manage its memory. And calling popFront on it would be nonsensical. It's not a range and shouldn't be one. So, it's just not going to work to expect a container to function in exactly the same code that a dynamic array does. It would be closer to expect the range over a container to operate like a dynamic array does, but even then, that doesn't quite work, because dynamic arrays have operations which aren't range-based (like ~ and ~=), because they're a weird special case that's kind of trying to be a container without actually being a container.

It will work far better if your generic code is written to operate on ranges or on containers and _not_ dynamic arrays. If it's written to operate on ranges, then both arrays and a range over a container or any other kind of range will work with that code, whereas if it's written to work with a container, then it will work with whatever has the appropriate API - which _can_ be a dynamic array under a restricted set of operations, but frequently won't be. Restricting yourself to using [] on the container _would_ make it work with dynamic arrays, and some functions like remove might work, but you do have to be a bit careful when trying to use dynamic arrays and containers interchangebly, because dynamic arrays really aren't proper containers. Static arrays are actually closer, but they're value types, whereas containers will normally be reference types, so passing them around will have different semantics.

Dynamic arrays in D are kind of weird beasts. They're _very_ useful the way that they are, but their quirkiness can be problematic if you're not careful, and the fact that they're _sort of_ containers but not is definitely one place that throws people off.

- Jonathan M Davis