1

I want to keep an ordered set of records and the standard provides me with RedBlackTree. The record is of type Tuple!(string, uint). Here's what it looks like:

import std.json : parseJSON;

    uint[string] wordTable;
    import std.datetime.stopwatch : StopWatch, AutoStart;

    auto sw = StopWatch(AutoStart.yes);
    const auto j = parseJSON(get(link));
    const long downloadTime = sw.peek.total!"msecs";

    import std.typecons : Tuple, tuple;
    import std.container.rbtree : RedBlackTree;
    import std.functional : binaryFun;

    RedBlackTree!(Tuple!(string, uint), binaryFun!("a[1] > b[1]")) records;

    foreach (node; j["posts"].array()) {
        import std.stdio : writeln;
        import std.utf : decode;

        if ("com" in node) {
            import std.algorithm : splitter;

            foreach (word; getStr(node["com"].str()).splitter(' ')) {
                import std.string : strip;

                if (word.strip().length > 0)
                    wordTable.require(word, 0)++;

                records ~= (tuple(word, wordTable[word])); // error
            }
        }
    }

Now primarily I had used insert() method to add a record to the records but it causes segfault in runtime. So I decided to use ~= in hopes for better error messages. And here's what the compiler says:

Error: cannot append type Tuple!(string, uint) to type std.container.rbtree.RedBlackTree!(Tuple!(string, uint), binaryFun, false)

According to https://dlang.org/phobos/std_container_rbtree.html#.RedBlackTree I have to provide a type such that calling less(a, b) on it returns a boolean. So I went ahead and created a type for it:

struct Record {
    string key;
    uint value;

    int opCmp(ref const Record other) const {
        return value - other.value;
    }
}

// bool less(Record a, Record b) {
//  return a < b;
// }

void main(string[] args) {
    import std.stdio : writeln, writefln;

    if (args.length < 3) {
        writeln("Must have 2 arguments " ~ "first argument is the link, "
                ~ "the second one is for minimum repeatation threshold. Exiting.");
        import core.stdc.stdlib : exit;

        exit(-1);
    }

    const auto link = parseLink(args[1]);
    const auto threshold = atoui(args[2]);

    import std.json : parseJSON;

    uint[string] wordTable;
    import std.datetime.stopwatch : StopWatch, AutoStart;

    auto sw = StopWatch(AutoStart.yes);
    const auto j = parseJSON(get(link));
    const long downloadTime = sw.peek.total!"msecs";

    import std.container.rbtree : RedBlackTree;
    import std.functional : binaryFun;

    RedBlackTree!Record records;

    foreach (node; j["posts"].array()) {
        import std.utf : decode;

        if ("com" in node) {
            import std.algorithm : splitter;

            foreach (word; getStr(node["com"].str()).splitter(' ')) {
                import std.string : strip;

                if (word.strip().length > 0)
                    wordTable.require(word, 0)++;

                records ~= (Record(word, wordTable[word]));
            }
        }
    }

This time the compiler complains:

Error: cannot append type Record to type std.container.rbtree.RedBlackTree!(Record, "a < b", false)

So the gist of the question is, if I have an RedBlackTree with a custom binaryFun, how can I add an instance of a tuple or a custom type to it?

Alireza S.N
  • 209
  • 1
  • 4
  • 10
noconst
  • 639
  • 4
  • 15
  • The comparison function should be a string, not an actual function. So, replace `binaryFun!("a[1] > b[1]")` in your initial code with just `"a[1] > b[1]"` – brianush1 Apr 14 '20 at 03:11
  • RedBlackTree does not overload `~=`, so you have to use `insert`. – weltensturm Apr 14 '20 at 12:51

0 Answers0