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

 雷神白中凌 发布于 2023-02-08 19:32

我试图在Haxe3中为模板类型A编写一个通用比较函数(如c strcmp),假设此模板类型具有小于或等于运算符"<=".

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

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

所以,我用"le"函数尝试了相同的技术:

class Main {
    @:generic static public function compare_(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_函数,使其适用于任何模板类型(Int,Float,其他具有重载运算符的类型),并定义了"<="运算符?

以下是我的尝试:

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

这当然不编译.Haxe抱怨"le"未定义.

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

提前致谢.


更新:我做了一些额外的阅读,并认为我可能能够le使用usingcallback机制将方法注入我想要的每种类型.请参阅我的相关问题,"导入和使用可能不会在类型声明后出现" - 使用魔法的haxe.

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

    2023-02-08 19:33 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有