how to write a generic compare function in Haxe (haxe3)

Viewed 1505

I am trying to write a generic compare function (like the c strcmp) in Haxe3 for a template type A, assuming that this template type has a less-than-or-equal-to operator "<=".

I saw in the Haxe3 documentation (http://haxe.org/manual/haxe3/features) that you can do a similar job if you want to assume that a template type has the new function:

@:generic static function foo<T:{function new(s:String):Void;}>(t:T) {
    trace(Type.typeof(t)); // TClass([class String]) / TClass([class Template])
    return new T("foo");
}

So, I tried the same technique with a "le" function:

class Main {
    @:generic static public function compare_<A:{function le(y:A):Bool;}>(x:A,y:A): Int {
        if (x.le(y) && y.le(x)) return 0;
        else if (x.le(y)) return -1;
        else return 1;
    }


    static function main() {
        var a:MyInt  = new MyInt(1);
        var b:MyInt  = new MyInt(2);
        trace(compare_(a,b));
    }
}

class MyInt {
    var data:Int;
    public function new(i:Int) {this.data = i; }
    public function le(y:MyInt){return data <= y.data;}
}

The compare_ function above works fine for any type with the prerequisite "le" function. The above code returns -1 as expected. But it is rather inconvenient, obviously, to create a new class for Int, just to provide the le function. My question is, is there a way to re-write the compare_ function to make it work for any template type (Int,Float, other types with overloaded operators) with a "<=" operator defined?

The following is what I have tried:

@:generic static public function compare_<A:{@:op(X <= Y) function le(x:A,y:A):Bool;}>(x:A,y:A): Int {
     if (x <= y && y <= x) return 0;
     else if (x <= y) return -1;
     else return 1;
 }

which of course does not compile. Haxe complains that "le" is undefined.

I am looking for lightweight solutions without involving macros, as I intend to re-use the haxe generated code in other languages without dependance on Boot. or scuts. Dynamic is also not good for my purposes as there is no type-safety at all.

Thanks in advance.


Update: I did some additional reading, and figured I might be able to inject an le method the hard way into every type I want, using the using and callback mechanism. Please see my related question on that "import and using may not appear after a type declaration" -- the haxe using magic.

1 Answers
Related