【问题标题】:how to write a generic compare function in Haxe (haxe3)如何在 Haxe (haxe3) 中编写通用比较函数
【发布时间】:2013-12-20 20:09:10
【问题描述】:

我正在尝试在 Haxe3 中为模板类型 A 编写通用比较函数(如 c strcmp),假设此模板类型具有小于或等于运算符“

我在 Haxe3 文档 (http://haxe.org/manual/haxe3/features) 中看到,如果您想假设模板类型具有新功能,您可以执行类似的工作:

@: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");
}

所以,我用“le”函数尝试了同样的技术:

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

上面的 compare_ 函数适用于任何具有先决条件“le”函数的类型。上面的代码按预期返回 -1。但显然,为 Int 创建一个新类,只提供le 函数是相当不方便的。我的问题是,有没有办法重写 compare_ 函数,使其适用于定义了“

以下是我尝试过的:

@: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;
 }

当然不能编译。 Haxe 抱怨“le”未定义。

我正在寻找不涉及宏的轻量级解决方案,因为我打算在其他语言中重用 haxe 生成的代码而不依赖于 Boot。或scuts。动态也不适合我的目的,因为根本没有类型安全。

提前致谢。


更新: 我做了一些额外的阅读,并认为我可以使用using 和callback 机制将le 方法注入到我想要的每种类型中。请参阅我关于 "import and using may not appear after a type declaration" -- the haxe using magic 的相关问题。

【问题讨论】:

  • 不确定我是否完全理解了您的问题。 Reflect.compare(a,b) 是否接近您正在寻找的内容? api.haxe.org/Reflect.html#compare 这是一个@:coreApi,这意味着它是为每个平台单独实现的。在此处查看 Javascript 的实现:github.com/HaxeFoundation/haxe/blob/development/std/js/_std/… .... 不知道如何使用它或模板的“le()”函数进行比较...
  • 谢谢,杰森。我试过 Reflect.compare(a,b)。但我希望 a、b 都来自模板类型 T。我记得 haxe 编译告诉我只有类型只在运行时知道,而不是编译时知道。类似function compare_&lt;A&gt;(x:A,y:A):Int { return Reflect.compare(a,b); }。
  • 我想我想要一些可以隐式使用“
  • 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. 没有这样的解决方案。当实际上只有类型参数时,您一直在谈论模板。这是问题的一个重要部分。如果你想拥有模板的力量,你将不得不使用宏。或者你必须使用反射,但这也有局限性。您必须删除一些限制以留出解决方案空间;)
  • @back2dos。这应该是语言问题。 Haxe 类型参数在我看来类似于 C++ 模板类型。所以,这就是我所说的模板类型。我想要做的是能够在没有整个引导机制的情况下使用生成的 C++ 代码。到目前为止,C++ 不会检查类型参数是否定义了“

标签: generics haxe generic-programming


【解决方案1】:

处理问题的两种安全方法:

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

2。摘要

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-12
    • 2010-09-24
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 2019-04-27
    • 2019-03-19
    • 2013-12-29
    相关资源
    最近更新 更多