如何在Haxe中编写通用比较函数(haxe3) [英] how to write a generic compare function in Haxe (haxe3)

查看:190
本文介绍了如何在Haxe中编写通用比较函数(haxe3)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设这个模板类型有一个小于或等于运算符< =。我试图在Haxe3中为模板类型A编写一个通用比较函数(比如c strcmp)。 / p>

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



<$ (t:T){
trace(Type.typeof(t,t)){code> @:通用静态函数foo< T:{function new(s:String):Void;}& )); // TClass([class String])/ TClass([class Template])
return new T(foo);

$ / code>

因此,我尝试了使用le函数的相同技巧: p>

  class Main {
@:泛型静态公共函数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返回1;


$ b静态函数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_函数以使其适用于定义了< =运算符的任何模板类型(Int,Float,带有重载运算符的其他类型)?



以下是我试过的内容:

  @:generic (x:A,y:A):Bool;}>(x:A,y:A):Int {$ b $如果(x <= y&& y <= x)则返回0; 
else if(x <= y)返回-1;
else返回1;
}

哪些当然不会编译。 Haxe抱怨说le是未定义的。



我正在寻找不涉及宏的轻量级解决方案,因为我打算在没有依赖的情况下重新使用haxe生成的其他语言代码在启动。或者scuts。动态对我来说也不好,因为根本没有类型安全。



预先感谢。



< hr>

更新:
我做了一些额外的阅读,并认为我可以注入 le 方法使用 callback 机制,使用来实现我想要的每种类型。请参阅我的相关问题,该

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



1。宏



  class Main {
static 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。摘要



 抽象比较器< T>({f:T-> Int}){
public function new f)
this = {f:f};

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

@:从静态函数fromInt(i:Int)
return simple(i);

:从静态函数fromFloat(f:Float)
return simple(f);

@:从静态函数fromString(s:String)
返回简单(s);

@从静态函数fromComparable< A>(o:{function compareTo(other:A):Int;})
return new Comparator(o.compareTo);

静态函数简单< X>(o:X):比较器< X>
返回新的比较器(Reflect.compare.bind(o));

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

静态函数main(){
函数可比较(值)
返回{
值:值,
compareTo:函数(其他)
返回Reflect.compare(value,other.value)
}
trace(compare_(1,2));
trace(compare_(1.5,2.5));
trace(比较_('foo','bar'));
trace(比较_(可比较(1),可比较(2)));
}
}


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.

解决方案

Two type safe ways to deal with the problem:

1. Macros

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. Abstracts

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

这篇关于如何在Haxe中编写通用比较函数(haxe3)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆