thor
thor

Reputation: 22530

haxe operator overloading ==, Class not found error for template parameters

I am trying to overload the equals (==) operator on a custom "pair" type, as follows:

private typedef Data<A, B> = { a: A, b: B } 

abstract Pair<A, B>(Data<A, B>) {
public var a(get, set):A;
public var b(get, set):B;

public function equals1(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool {
       return (lhs.a == rhs.a && lhs.b == rhs.b);
}

@:op(X == Y) static public function equals(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool {
       return (lhs.a == rhs.a && lhs.b == rhs.b);
}

public inline function new(a:A, b:B) this =
        { a: a, b: b };
inline function get_a():A 
    return this.a;

inline function get_b():B 
    return this.b;

inline function set_a(v:A):A
    return this.a = v;

inline function set_b(v:B):B
    return this.b = v;

}

I am new to abstract classes and operator overloading. But the overloading part is almost copied verbatim from the haxe documentation example. The overloaded operator is intended to test equality of two pairs. However, when I compiled the code to neko, I get an error:

Pair.hx:11: lines 11-13 : Class not found : A

I am confused here, because as you can see immediately above the overloaded function, there is an plain function version "equals1", which compiles just fine. As soon as I add @:op(X == Y), the template parameter A in Pair is "not found".

My questions is how to make this overloading work, and what went wrong in my code?

Thanks in advance.

P.S. I am using Haxe Compiler 3.0.1, installed on Windows.

--Update--: I looked over the code again, it seems that declaring the equals function "static" is causing the problem. If I add "static" to the plain function,

static public function equals1(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool { 
 ...

The same error is reported.

--update--: The answer by back2dos is correct:

private typedef Data<A, B> = { a: A, b: B } 

abstract Pair<A, B>(Data<A, B>) {
public var a(get, set):A;
public var b(get, set):B;

public function equals1(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool {
    return (lhs.a == rhs.a && lhs.b == rhs.b);
}

@:op(X == Y) static public function equals<A, B>(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool {
    return (lhs.a == rhs.a && lhs.b == rhs.b);
}

public inline function new(a:A, b:B) this =
{ a: a, b: b };
inline function get_a():A 
                        return this.a;

inline function get_b():B 
                        return this.b;

inline function set_a(v:A):A
                           return this.a = v;

inline function set_b(v:B):B
                           return this.b = v;

}

class Main {
static public function main() {
    var p1 = new Pair(1,2), p2 = new Pair(1,5);
    trace (p1 == p2);

}
}

Outputs: Main.hx:34: false Main.hx:35: true

Upvotes: 3

Views: 579

Answers (1)

back2dos
back2dos

Reputation: 15623

The issue here is that type parameters declared on classes/abstracts are scoped to instances/values and thus are not defined in the static context.

Therefore, you need to parametrize the function:

@:op(X == Y) static public function equals1<A, B>(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool;

Upvotes: 6

Related Questions