Generics 如何在Haxe(haxe3)中编写通用比较函数

Generics 如何在Haxe(haxe3)中编写通用比较函数,generics,haxe,generic-programming,Generics,Haxe,Generic Programming,我试图在Haxe3中为模板类型a编写一个通用比较函数(如c strcmp),假设此模板类型具有小于或等于运算符“两种类型安全的方法来处理此问题: 1.宏 主类{ 宏静态公共函数比较(a,b) 返回宏@:pos(a.pos){ 变量a=$a, b=b美元; 如果(a)不确定我是否完全理解了你的问题。是Reflect.compare(a,b)与你想要的接近吗?这是一个@:coreApi,这意味着它是针对每个平台分别实现的。请参见此处的Javascript实现:……不确定如何使用该或模板的“le()进

我试图在Haxe3中为模板类型a编写一个通用比较函数(如c strcmp),假设此模板类型具有小于或等于运算符“两种类型安全的方法来处理此问题:

1.宏
主类{
宏静态公共函数比较(a,b)
返回宏@:pos(a.pos){
变量a=$a,
b=b美元;

如果(a)不确定我是否完全理解了你的问题。是Reflect.compare(a,b)与你想要的接近吗?这是一个
@:coreApi
,这意味着它是针对每个平台分别实现的。请参见此处的Javascript实现:……不确定如何使用该或模板的“le()进行比较“不过函数…谢谢,Jason。我试过Reflect.compare(a,b)。但我希望a,b都来自模板类型T。我记得haxe编译告诉我,只有该类型在运行时才知道,而不是在编译时。类似于
function compare_ux(x:a,y:a):Int{return Reflect.compare(a,b);}
。我想我想要一些可以隐式使用"
我正在寻找不涉及宏的轻量级解决方案,因为我打算在其他语言中重复使用haxe生成的代码,而不依赖于引导或scuts。动态对我来说也不好,因为根本没有类型安全性。
没有这样的解决方案。你一直在谈论模板,而实际上只有类型米。这是问题的一个重要部分。如果你想拥有模板的功能,你必须使用宏。或者你必须使用反射,但这也有局限性。你必须删除一些约束以允许解决方案空间;)这可能是一个语言问题。HAXE类型参数看起来与C++模板类型类似。所以,这就是模板类型的意思。我想做的是,可以使用生成的C++代码而不需要整个引导机制。到目前为止,C++将不会检查类型参数是否有“一个”。
@: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");
}
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;}
}
@: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;
 }
class Main {
    macro static public function compare_(a, b)
        return macro @:pos(a.pos) { 
            var a = $a, 
            b = $b; 
            if (a <= b) 
                if (b <= a) 0;
                else -1;
            else 1;
        }  

    static function main() {
        var a = 1,
            b = 2;
        trace(compare_(a,b));
    }
}
abstract Comparator<T>({f: T->Int }) {
    public function new(f) 
        this = { f: f };

    public function compare(other:T):Int
        return this.f(other);

    @:from static function fromInt(i:Int)
        return simple(i);

    @:from static function fromFloat(f:Float)
        return simple(f);

    @:from static function fromString(s:String)
        return simple(s);

    @:from static function fromComparable<A>(o:{ function compareTo(other:A):Int; })
        return new Comparator(o.compareTo);

    static function simple<X>(o:X):Comparator<X>
        return new Comparator(Reflect.compare.bind(o));
}

class Main {
    static public function compare_<A>(a:Comparable<A>, b:A)
        return a.compare(b);

    static function main() {
        function comparable(value)
             return { 
                 value: value, 
                 compareTo: function(other) 
                     return Reflect.compare(value, other.value) 
             }          
        trace(compare_(1,2));
        trace(compare_(1.5,2.5));
        trace(compare_('foo','bar'));
        trace(compare_(comparable(1),comparable(2))); 
    }
}