Thread overview
DList.linearRemove on last element -- returned range is non-empty?
Sep 05, 2014
rcor
Sep 05, 2014
monarch_dodra
Sep 05, 2014
rcor
September 05, 2014
According to the docs, linearRemove on a DList returns "A range spanning the remaining elements in the container that initially were right after r" (http://dlang.org/library/std/container/DList.linearRemove.html)
This seems to work fine except when I want to remove the last element. I would expect to get an empty range, as there are no elements following the removed element. Instead, I get a non-empty range (referencing un-initialized memory?
Example:

  auto list = DList!int([1,2,3,4,5]);
  auto r = list[].drop(4); // r is a view of the last element of list
  assert(r.front == 5 && r.walkLength == 1);
  r = list.linearRemove(r.take(1));
  assert(r.empty); // fails

As to why this is an issue:
I'm trying to create a list that lazily removes flagged elements. I expect to make frequent removals from arbitrary points in the list. Rather than walking the list to find an element I want to remove, I flag elements for removal. During the next iteration of the list, the range skips over and removes elements that are flagged. This fails when the last element is flagged for removal -- because the range returned by linearRemove is non-empty I'm not aware that I just removed the last element and continue trying to pop elements.
You can see a Gist here:
https://gist.github.com/murphyslaw480/53869a32402ba1fe5621
I mention this because I may be going about this all wrong, and shouldn't be using linearRemove like this at all. However, I wanted a linear data structure that allowed me to efficiently remove arbitrary elements without relocating whole chunks of arrays.
September 05, 2014
On Friday, 5 September 2014 at 15:33:16 UTC, rcor wrote:
> According to the docs, linearRemove on a DList returns "A range spanning the remaining elements in the container that initially were right after r" (http://dlang.org/library/std/container/DList.linearRemove.html)
> This seems to work fine except when I want to remove the last element. I would expect to get an empty range, as there are no elements following the removed element. Instead, I get a non-empty range (referencing un-initialized memory?
> Example:
>
>   auto list = DList!int([1,2,3,4,5]);
>   auto r = list[].drop(4); // r is a view of the last element of list
>   assert(r.front == 5 && r.walkLength == 1);
>   r = list.linearRemove(r.take(1));
>   assert(r.empty); // fails
>
> As to why this is an issue:
> I'm trying to create a list that lazily removes flagged elements. I expect to make frequent removals from arbitrary points in the list. Rather than walking the list to find an element I want to remove, I flag elements for removal. During the next iteration of the list, the range skips over and removes elements that are flagged. This fails when the last element is flagged for removal -- because the range returned by linearRemove is non-empty I'm not aware that I just removed the last element and continue trying to pop elements.
> You can see a Gist here:
> https://gist.github.com/murphyslaw480/53869a32402ba1fe5621
> I mention this because I may be going about this all wrong, and shouldn't be using linearRemove like this at all. However, I wanted a linear data structure that allowed me to efficiently remove arbitrary elements without relocating whole chunks of arrays.

I actually noticed this in code yesterday. Could you please file it? I'll get to fixing it, I'm working on DList right now.
September 05, 2014
On Friday, 5 September 2014 at 17:17:54 UTC, monarch_dodra wrote:
>
> I actually noticed this in code yesterday. Could you please file it? I'll get to fixing it, I'm working on DList right now.

https://issues.dlang.org/show_bug.cgi?id=13425

Thanks, its impressive how fast you respond to these posts.