Thread overview
Adding item to a rbtree with a custom binaryFun
Apr 13, 2020
Adnan
Apr 14, 2020
Adnan
April 13, 2020
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 used `insert()` method to add a record to the records but it causes segfault in runtime. So I decided to use ~= to see what's going on. Here's what the compiler says:

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


So the gist of the question is, if I have an RedBlackTree with a custom binaryFun, how can I add tuples to it?
April 14, 2020
On Monday, 13 April 2020 at 23:59:20 UTC, Adnan wrote:
> 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 used `insert()` method to add a record to the records but it causes segfault in runtime. So I decided to use ~= to see what's going on. Here's what the compiler says:
>
> Error: cannot append type Tuple!(string, uint) to type std.container.rbtree.RedBlackTree!(Tuple!(string, uint), binaryFun, false)
>
>
> So the gist of the question is, if I have an RedBlackTree with a custom binaryFun, how can I add tuples to it?

I also tried creating a new type:
		struct Record {
		string k;
		uint v;

		int opCmp(ref const Record other) const {
			return v - other.v;
		}
	}
	
	bool less(Record a, Record b) {
            return a < b;
    }

	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]);
			}
		}
	}

Compiler says:

 Error: cannot append type Record to type std.container.rbtree.RedBlackTree!(Recor
d, "a < b", false)
source/app.d(153,18): Error: no [] operator overload for type Record
source/app.d(157,58): Error: no [] operator overload for type Record
source/app.d(158,40): Error: no [] operator overload for type Record
April 13, 2020
On 4/13/20 7:59 PM, Adnan wrote:
> 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;
>

// instead of this:

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

// do this: (note you don't need binaryFun)
       auto records = new RedBlackTree!(Tuple!(String, uint), "a[1] > b[1]");

> 
>      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 used `insert()` method to add a record to the records but it causes segfault in runtime.

Because RedBlackTree is a class, so you need to initialize it with a call to new.

> So I decided to use ~= to see what's going on. Here's what the compiler says:
> 
> Error: cannot append type Tuple!(string, uint) to type std.container.rbtree.RedBlackTree!(Tuple!(string, uint), binaryFun, false)

Because RedBlackTree doesn't overload appending.

-Steve