Removal from std.container.Array.

Jakob Ovrum jakobovrum at gmail.com
Mon Feb 10 17:32:38 PST 2014


On Monday, 10 February 2014 at 21:47:35 UTC, Ty Overby wrote:
> I have to be missing something really basic.  It couldn't 
> possibly be this hard to remove an element from an array.

I think the correct solution is:

systems.linearRemove(systems[].find(system)[0 .. 1]);

Usually containers have an overload of *[Rr]emove that takes 
`Take!Range`, allowing:

systems.linearRemove(systems[].find(system).takeOne());

std.container.Array not having overloads for `Take!Range` looks 
like an oversight.

To the uninitiated this can look ridiculous, but hear me out 
first.

First of all, the unary slice operation (the empty brackets: []) 
is the container primitive to get a range spanning the entire 
container. It is arguably the most fundamental container 
primitive, and is crucial when using other container primitives, 
as they often take range parameters. IMO, it would be a nice 
compiler enhancement to raise a tailored error message in cases 
where [] is forgotten (probably non-trivial to implement, though).

With that out of the way: in D, both ranges and containers follow 
the principle that primitives are subject to restrictions on 
algorithmic complexity to avoid the quadratic complexity 
minefield that the Java approach heralds through deceptive 
abstraction of linear algorithms (of which 
ArrayList/List/Collection.remove is a good example). Therefore, a 
primitive equivalent of Java's List/Collection.remove is not 
welcome in D.

Often when linear search is required for this kind of operation, 
the user has chosen the wrong data structure, so the absence of 
deceptive abstractions from the core API is *usually* a 
non-issue. Of course, sometimes linear search is perfectly 
justified, especially when it comes to (smallish) arrays, or code 
that is only run very rarely. In these cases, the equivalent D 
code using range algorithms (shown above) has advantages; we can 
glean two important artefacts: a) linear search is at play 
(because of `find`), and b) only the first element found is 
removed. The obvious disadvantage is that writing such code in 
the first place requires a relatively high degree of familiarity 
with Phobos containers and ranges. That said, it's probably 
offset by the fact that when you *do* start picking up Phobos' 
generic algorithms and primitives, you can apply them everywhere 
- learning the API of a new container is just a matter of 
glancing over what primitives it supports. Better documentation - 
such as adding examples - is definitely in order to ease this 
learning, though.


More information about the Digitalmars-d-learn mailing list