Search code examples
containersd

D: Not clear about how to use std.container structs


I'm trying to learn how to use the various container structures available in std.container, and I'm having trouble understanding how to do the following:

1) How do I create an empty container? For instance, suppose I have a user-defined class Foo, and want to create an empty DList that is supposed to contain Foo objects. What's the syntax I should use?

2) Suppose a and b are both DList!int. I try to call a ~ b, and the compiler tells me I can't. However, I can see that DList has overloaded that operator. What did I miss?


Solution

  • There are three ways to create a new container,

    1. the unified way, using std.container.make:

      auto list1 = make!(DList!int)();
      auto list2 = make!(DList!int)(1, 2);
      
    2. using struct initializer syntax:

      auto list1 = DList!int();
      
    3. using the helper functions for classes:

      auto tree1 = redBlackTree!int();
      auto tree2 = redBlackTree!int(1, 2);
      

    The difference between those is that some data structures are implemented using classes and some with structs. And using make, you will not need to know but the first way as there is no effective difference.

    Regarding the appending operator, you will need to append a range from DList!T rather than DList!T itself. Example:

    auto list1 = make!(DList!int)(1, 2);
    auto list2 = make!(DList!int)(3, 4);
    list1 ~= list2[]; //notice the square brackets, which represent obtaining a slice (InputRange) from the `DList`, or more specifically calling `opSlice`.
    

    As a more complete example on usage, check the following:

    import std.container;
    import std.stdio;
    
    class Foo {
      int i;
    
      this(int i) {
        this.i = i;
      }
    
      void toString(scope void delegate(const(char)[]) sink) const {
        // this is a non allocating version of toString
        // you can use a normal `string toString()` function too
        import std.string : format;
        sink("Foo: %s".format(i));
      }
    }
    
    void main() {
      auto odds = make!(DList!Foo)();
      odds.insert(new Foo(3));
      odds.insert(new Foo(5));
      writeln("Odds: ", odds[]);
    
      odds.insertFront(new Foo(1));
      writeln("Odds: ", odds[]);
    
      auto evens = make!(DList!Foo)();
      evens.insert(new Foo(2));
      evens.insert(new Foo(4));
    
      writeln("Evens: ", evens[]);
    
      odds.insert(evens[]);
      writeln("Odds then evens: ", odds[]);
    
      odds ~= evens[];
      writeln("Odds then evens x 2: ", odds[]);
    }
    

    You can run this online here: http://dpaste.dzfl.pl/f34b2ec8a445