March 24
module bag;

import std.container.rbtree : RedBlackTree;  // template
import std.stdio : writeln;

struct Location
{
    int r;  // row
    int c;  // column
}

struct Node
{
    this(Location locale, uint f) {
        this.locale = locale;
        this.f = f;
    }
    Location locale;
    uint f;
}

struct Bag
{
    void addTo(Node node) {
        this.rbt.insert(node);          // add to red black tree, rbt
        this.aa[node.locale] = node.f;  // add to associative array, aa
    }

    void display() {
        writeln("======= Bag: ", this.name, " =======");
        writeln("associative array of ", this.name, " has length ", this.aa.length);
        foreach(keyValuePair; this.aa.byKeyValue())
        {
            writeln("Key: ", keyValuePair.key, ", Value: ", keyValuePair.value);
        }
        writeln("red black tree of ", this.name, " has length ", this.rbt.length);
        foreach(node; this.rbt)
        {
            writeln("node: ", node);
        }
    }

    void setName(string n) { this.name = n; }

    string name;

    uint[Location] aa;  // associative array

    auto rbt = new RedBlackTree!(Node, "a.f < b.f", true); // true: allowDuplicates
}

unittest
{

Bag paper;
Bag cloth;

paper.setName("Brown");
cloth.setName("Green");

paper.addTo( Node(Location(1,2),   33) );
paper.addTo( Node(Location(3,4),   20) );  // duplicate

cloth.addTo( Node(Location(9,10),  20) );  // duplicate
cloth.addTo( Node(Location(11,12), 97) );
cloth.addTo( Node(Location(13,14), 20) );  // duplicate

paper.display;
cloth.display;


}

rdmd -main -unittest bag.d

returned the following:

======= Bag: Brown =======
associative array of Brown has length 2
Key: Location(1, 2), Value: 33
Key: Location(3, 4), Value: 20
red black tree of Brown has length 5
node: Node(Location(3, 4), 20)
node: Node(Location(9, 10), 20)
node: Node(Location(13, 14), 20)
node: Node(Location(1, 2), 33)
node: Node(Location(11, 12), 97)
======= Bag: Green =======
associative array of Green has length 3
Key: Location(9, 10), Value: 20
Key: Location(13, 14), Value: 20
Key: Location(11, 12), Value: 97
red black tree of Green has length 5
node: Node(Location(3, 4), 20)
node: Node(Location(9, 10), 20)
node: Node(Location(13, 14), 20)
node: Node(Location(1, 2), 33)
node: Node(Location(11, 12), 97)
1 modules passed unittests

Why aren't the redblack trees being split up properly between paper and cloth like the associative arrays? It's like the trees are sharing their values across the separate struct objects.


Note: I then created another struct 99% identical to Bag but this time called it Sack. So like the following:

Bag paper;
Sack cloth;

This time it worked as expected:

======= Bag: Brown =======
associative array of Brown has length 2
Key: Location(1, 2), Value: 33
Key: Location(3, 4), Value: 20
red black tree of Brown has length 2
node: Node(Location(3, 4), 20)
node: Node(Location(1, 2), 33)
======= Sack: Green =======
associative array of Green has length 3
Key: Location(9, 10), Value: 20
Key: Location(13, 14), Value: 20
Key: Location(11, 12), Value: 97
red black tree of Green has length 3
node: Node(Location(9, 10), 20)
node: Node(Location(13, 14), 20)
node: Node(Location(11, 12), 97)
1 modules passed unittests

March 24

On Monday, 24 March 2025 at 17:39:34 UTC, WhatMeWorry wrote:

>
    void setName(string n) { this.name = n; }

    string name;

    uint[Location] aa;  // associative array

    auto rbt = new RedBlackTree!(Node, "a.f < b.f", true); // true: allowDuplicates

You would think that this would create a new instance every time that the struct is instantiated.

Unfortunately what it does in fact do, is create a RedBlackTree instance at compiletime, emit it into the binary, and assign its reference as the default initializer of the rbt field.

I think probably the easiest fix is make Bag a class and assign new RedBlackTree in the constructor.