www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - DList.linearRemove on last element -- returned range is non-empty?

reply "rcor" <murphyslaw480 gmail.com> writes:
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.
Sep 05 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
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.
Sep 05 2014
parent "rcor" <murphyslaw480 gmail.com> writes:
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.
Sep 05 2014