www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - std.containers - WAT

reply James Miller <james aatch.net> writes:
In helping someone in D.learn, I ended up looking through the
documentation and code for std.containers.

There is a lot wrong with whats going on there right now.

For a start, the documentation is pretty unclear, The table for the
container primitives is poorly explained, and the complexity columns
wraps on most screen sizes, making understanding them a nightmare. The
explanations for what things are, and what they do is pretty unclear,
and since its not completely standardized over the different
containers, you end up with some truly mindboggling documentation. A
good example is this: "c.removeAny()	- Removes some element from c and
returns it.", what some element at random? Or does it take an argument
that isn't show like what is implied by this: "c.stableRemoveAny(v) -
Same as c.removeAny(v), but is guaranteed to not invalidate any
iterators.", but that doesn't seem right because SList has "T
removeAny() - Picks one value from the front of the container, removes
it from the container, and returns it." which doesn't take a value.
This is endless confusing, and I ended up consulting the unittests in
order to understand what the hell was going on.

Then there are the strange input and output types/value for the
arguments. For example, why does SList.linearRemove return an empty
Range on the Take!Range overload, and an empty Range on the Range
overload? In fact, why are any of the functions accepting and
returning /Ranges/ which are internal types specific to the container?
Why don't they all just take a type that can be converted to a range?
As is stands, you end up with ridiculous requirements like:

    //Remove a single element from an SList, given its "index"
    size_t index = 5;
    SList!int s = [0,1,2,3,4,5,6,7,8,9];
    auto r = s[0..index-1];
    auto r1 = take(r, 1);
    s.linearRemove(r1);
    assert(equal(s, [0,1,2,3,5,6,7,8,9]);

Which could be replaced with an overload for linearRemove that looks like this:

    /** Removes the element at index, return false if the element
could not be removed **/
    bool linearRemove(size_t index){...}

Almost all of the "primitives" seem to be based around adding or
removing from the front or back of the container, but there's no
random-access removal. And since the behaviour is Container specific,
its impossible to figure out what a function does anyway! For example,
SList's linearRemove(Range) just removes the front elements from the
container, not obvious.

Is there any reason why things are the way they are? Because all I see
are people getting exited about ranges and operator overloading and
not really thinking about what a useful set of features any given
container should have.

--
James Miller

P.S. I'm happy to help out improving the documentation, but I have no
idea what these things are supposed to do in the first place...
Mar 27 2012
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/27/12 7:46 PM, James Miller wrote:
 For a start, the documentation is pretty unclear, The table for the
 container primitives is poorly explained, and the complexity columns
 wraps on most screen sizes, making understanding them a nightmare.

I plan to redo that table. A screenshot would help - thanks!
 The
 explanations for what things are, and what they do is pretty unclear,
 and since its not completely standardized over the different
 containers, you end up with some truly mindboggling documentation. A
 good example is this: "c.removeAny()	- Removes some element from c and
 returns it.", what some element at random?

Actually removeAny is one of the better ones. It just removes an element from the container that is most convenient to the container.
 Or does it take an argument
 that isn't show like what is implied by this: "c.stableRemoveAny(v) -
 Same as c.removeAny(v), but is guaranteed to not invalidate any
 iterators.", but that doesn't seem right because SList has "T
 removeAny() - Picks one value from the front of the container, removes
 it from the container, and returns it." which doesn't take a value.
 This is endless confusing, and I ended up consulting the unittests in
 order to understand what the hell was going on.

That's a mistake in the documentation, stableRemoveAny does not take a value. I just fixed it in https://github.com/D-Programming-Language/phobos/commit/9d7168be5fc91da74231ab86d989ac6013280830.
 Then there are the strange input and output types/value for the
 arguments. For example, why does SList.linearRemove return an empty
 Range on the Take!Range overload, and an empty Range on the Range
 overload?

It's simple - generally removeRange returns the portion after the deleted part. The structure of SList dictates that removing a range means removing through the end. Removing a Take!Range naturally will return some potentially nonempty range.
 In fact, why are any of the functions accepting and
 returning /Ranges/ which are internal types specific to the container?

Ranges are not internal to containers, they are the way containers are manipulated.
 Why don't they all just take a type that can be converted to a range?

I don't see the advantage of doing so.
 As is stands, you end up with ridiculous requirements like:

      //Remove a single element from an SList, given its "index"
      size_t index = 5;
      SList!int s = [0,1,2,3,4,5,6,7,8,9];
      auto r = s[0..index-1];
      auto r1 = take(r, 1);
      s.linearRemove(r1);
      assert(equal(s, [0,1,2,3,5,6,7,8,9]);

 Which could be replaced with an overload for linearRemove that looks like this:

      /** Removes the element at index, return false if the element
 could not be removed **/
      bool linearRemove(size_t index){...}

We can add overloads that use index-based operations, but generally you already have a range and would like to do a positioned delete. If you find yourself doing a lot of indexed operations in a SList, you chose the wrong containers.
 Almost all of the "primitives" seem to be based around adding or
 removing from the front or back of the container, but there's no
 random-access removal.

Why the quotes? More containers are likely to perform removal at an end efficiently than randomly positioned.
 And since the behaviour is Container specific,
 its impossible to figure out what a function does anyway! For example,
 SList's linearRemove(Range) just removes the front elements from the
 container, not obvious.

I'm not sure I get this. Might be a bug somewhere. The linearRemove primitive is supposed to do the same for all containers - remove a range in linear time.
 Is there any reason why things are the way they are? Because all I see
 are people getting exited about ranges and operator overloading and
 not really thinking about what a useful set of features any given
 container should have.

Proposals for improving things are always welcome.
 P.S. I'm happy to help out improving the documentation, but I have no
 idea what these things are supposed to do in the first place...

Just ask. Andrei
Mar 27 2012
prev sibling next sibling parent James Miller <james aatch.net> writes:
--000e0cdfdb520b22bc04bc4560e2
Content-Type: text/plain; charset=UTF-8

On 28 March 2012 15:28, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 In fact, why are any of the functions accepting and
 returning /Ranges/ which are internal types specific to the container?

Ranges are not internal to containers, they are the way containers are manipulated.

But there is a Range struct inside each container, it implements the Range interface, but as far as I am aware, it is its own type, and therefore anything that explicitly expects a Range is going to expecting its own internal type. From what I can tell, the internal Range struct on each container is just the underlying storage mechanism for that container, and you can even have more than one defined internal Range for a container. The issue comes about that several methods want that type. Now there may be some voodoo going on that I don't understand, but it seems to me that I can't do some thing like: SList!int s = [1,2,3,4,5,6,7]; s.linearRemove([4]) // Arrays are ranges To remove a certain value, because [4] is not a valid type, despite the fact that isForwardRange!(int[]) returns true. This is because although int[] is a range, it is not a Range (as in the inner type inside SList named Range). This is incredibly confusing to people reading the documentation, since Range and range could mean anything. I guess what I want is the why's for everything, why do things return certain values? Why do certain methods only accept data that was pulled from the container in the first place? Simply saying that some generally returns some value doesn't help, I need to know the whys behind it. Is is because the common use case is that, is it because it was the easiest way to do it, is it because you just randomly decided to because you felt that void was a cop-out? I just feel that the documentation could do with some work in this regard, but I wasn't there when this was being designed, I don't know the whys behind the decisions. If I point out where I think the documentation is lacking, simply in a "That is completely useless" kind of way, could somebody either update the documentation, or provide me with better explanations. I have also attached the screenshot you asked for, sorry for the quality, I don't have the tools on my machine to deal with images properly right now. -- James Miller --000e0cdfdb520b22bc04bc4560e2 Content-Type: image/jpeg; name="screengrab.jpg" Content-Disposition: attachment; filename="screengrab.jpg" Content-Transfer-Encoding: base64 X-Attachment-Id: f_h0btvc810 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 /9k= --000e0cdfdb520b22bc04bc4560e2--
Mar 27 2012
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, March 28, 2012 16:40:56 James Miller wrote:
 On 28 March 2012 15:28, Andrei Alexandrescu
 
 <SeeWebsiteForEmail erdani.org> wrote:
 In fact, why are any of the functions accepting and
 returning /Ranges/ which are internal types specific to the container?

Ranges are not internal to containers, they are the way containers are manipulated.

But there is a Range struct inside each container, it implements the Range interface, but as far as I am aware, it is its own type, and therefore anything that explicitly expects a Range is going to expecting its own internal type. From what I can tell, the internal Range struct on each container is just the underlying storage mechanism for that container, and you can even have more than one defined internal Range for a container. The issue comes about that several methods want that type. Now there may be some voodoo going on that I don't understand, but it seems to me that I can't do some thing like: SList!int s = [1,2,3,4,5,6,7]; s.linearRemove([4]) // Arrays are ranges To remove a certain value, because [4] is not a valid type, despite the fact that isForwardRange!(int[]) returns true. This is because although int[] is a range, it is not a Range (as in the inner type inside SList named Range). This is incredibly confusing to people reading the documentation, since Range and range could mean anything. I guess what I want is the why's for everything, why do things return certain values? Why do certain methods only accept data that was pulled from the container in the first place? Simply saying that some generally returns some value doesn't help, I need to know the whys behind it. Is is because the common use case is that, is it because it was the easiest way to do it, is it because you just randomly decided to because you felt that void was a cop-out? I just feel that the documentation could do with some work in this regard, but I wasn't there when this was being designed, I don't know the whys behind the decisions. If I point out where I think the documentation is lacking, simply in a "That is completely useless" kind of way, could somebody either update the documentation, or provide me with better explanations. I have also attached the screenshot you asked for, sorry for the quality, I don't have the tools on my machine to deal with images properly right now.

It's like iterators in C++. Each container has its own, and that's the type that you use to iterate over and manipulate the elements of a container. It's just that instead of using iterators, std.container is using ranges. As to why some functions require ranges from the container specifically, it's for the same reason that many functions on STL containers require iterators from the container specifically: they need to operate on those exact elements, not the values of those elements or some other iterator or range which points to the same values. They must operate on those exact elements. std.container still needs some work to be sure (parts of it are going to be redesigned to work with the custom allocators which are currently being worked on), and the documentation probably does need some work, but much of how it works is pretty much the same as how the containers work in C++. - Jonathan M Davis
Mar 27 2012