On Sunday, 18 March 2018 at 17:21:58 UTC, Steven Schveighoffer wrote:
On 3/18/18 8:34 AM, Viktor wrote:
Hey,

I'm trying to convert an old legacy app to D and have a couple of questions. It has been a very fun weekend!

First, I could not make std.container.rbtree use a delegate for a comparator. The docs say it should be possible, but I got a weird error.

I tracked it down to RedBlackTreee.opEquals() using explicit function when calling equals():

return equal!(function(Elem a, Elem b) => !_less(a,b) && !_less(b,a))(thisRange, thatRange);

When I removed the "function" things started compiling (I have yet to test the code due to question #2 below). I've done a dub -b unittest without issues so it might be OK.

So, the first...several questions are: do you think this change is safe and should I raise an issue in the bugzilla or do a PR for it on github?

Yes, seems like an oversight. RedBlackTree.opEquals was added almost 6 years ago, and it's possible this wouldn't have worked back then (https://github.com/dlang/phobos/pull/900)


Should it include a new unittest that makes sure rbtree can be instantiated with a delegate?

Definitely. Thanks for thinking of this!


The other part I'm still struggling with is about auto types. Can I store the rbtree type in the following class so it can be used from another method?

class Indexer(T, alias pred)
{
      alias RBType = RedBlackTree!(uint, (a, b) => comp(a, b));
    this(T storage)
    {
       this.storage = storage;

         this.index = new RBType();

    }


    void dumpIndex()
    {
        // how to get my dirty hands on the index here?

          // answer: just use it?

    }

    bool comp(uint i1, uint i2)
    {
       auto rec1 = storage[i1];
       auto rec2 = storage[i2];
       return pred(rec1, rec2);
    }

    private T storage;

      RBType index;

}


-Steve

Hi Steve, thanks for replying!

I've also noticed that RedBlackTree.opEquals() is like this from the initial pull request and was wondering if noone has been using a delegate and why...

On the second topic, I've tried that and it doesn't work. I have a minimal test program that shows the issue.

https://run.dlang.io/is/WNF78H

onlineapp.d(15): Error: need this for less of type bool(int a, int b) onlineapp.d(15): instantiated from here: Generic!((a, b) => less(a, b))

If I try using an explicit delegate in the alias:

onlineapp.d(15): Error: delegate `onlineapp.Custom.__dgliteral6` cannot be class members onlineapp.d(15): instantiated from here: Generic!(delegate (a, b) => less(a, b))

That seems reasonable to me, since the delegate needs a frame (for the this pointer) and there is no frame at that point.

I think in the end I'll need to plant an interface that RBTree will implement and use the interface instead.

The code in question:

class Generic(alias pred)
{
   void add(int a, int b)
   {
       import std.stdio : writeln;
       if (pred(a,b))
           writeln(a);
       else
           writeln(b);
   }
}

class Custom
{
    alias MyGeneric = Generic!( (a,b) => less(a,b) );
    private MyGeneric g;

    this ()
    {
        g = new MyGeneric;
    }

    void test()
    {
        g.add(5, 6);
    }

    bool less(int a, int b)
    {
        import std.stdio : writeln;
        writeln("Yup");
        return a < b;
    }
}

void main()
{
    auto t = new Custom;
    t.test;
}

Reply via email to