我正在尝试在Haxe3中为模板类型A编写一个通用比较函数(如c strcmp),假设此模板类型具有小于或等于运算符“&lt; =”。< / p>
我在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_函数,使其适用于任何模板类型(Int,Float,其他具有重载运算符的类型),并定义了“&lt; =”运算符?
以下是我的尝试:
@: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”未定义。
我正在寻找不涉及宏的轻量级解决方案,因为我打算在不依赖Boot的情况下在其他语言中重用haxe生成的代码。或者scuts。动态也不利于我的目的,因为根本没有类型安全。
提前致谢。
更新:
我做了一些额外的阅读,并认为我可能能够使用le
和using
机制以一种callback
方法将所有类型注入我想要的方法。请在"import and using may not appear after a type declaration" -- the haxe using magic上查看我的相关问题。
答案 0 :(得分:6)
处理问题的两种安全方式:
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)));
}
}