haxeneko

What is meant by being "physically equal" in Haxe?


I've been playing around with Neko Modules, but I think I'm getting some inconsistent behaviour.

var funcs = 0;
var objs = 0;
for (i in 0...m.globalsCount())
{
    var obj:Dynamic = m.getGlobal(i);

    if (Reflect.compareMethods(obj, init))
        trace("matched");

    if (Reflect.isFunction(obj))
        funcs++;
    else if (Reflect.isObject(obj))
        objs++;
}
trace('Functions: $funcs');
trace('Objects: $objs');

In the above code, when I run it the first time, I get a total of 4487 functions. If I remove a function, rebuild and run, I get the expected 4486.

I added the compareMethods comparison to compare the obj with init, where init is a function I declared in the Main file, but the trace is never output.

I glanced over at the code hint for the compareMethods function, and I stumbled across the following terminology: if 'f1' and the 'f2' are **physically** equal.

Now, they are both functions, and no where in the Haxe manual does it mention anything about physical functions. So I have a two part question, really.

What is a physical function, and how do I achieve the trace result as you would expect above? Thank you, in advance.


Solution

  • According to haxe unit tests (and js source of Reflect) Reflect.compareMethods returns true only if you are comparing any method of the same object to itself.

    // https://github.com/HaxeFoundation/haxe/blob/ff3d7fe6911ab84c370b1334d537a768a55cca56/tests/unit/src/unit/TestReflect.hx
    // 
    // t(expr) - expr should be true 
    // f(expr) - expr should be false 
    
    function testCompareMethods() {
        var a = new MyClass(0);
        var b = new MyClass(1);
        t( Reflect.compareMethods(a.add,a.add) );
        f( Reflect.compareMethods(a.add,b.add) );
        f( Reflect.compareMethods(a.add,a.get) );
        f( Reflect.compareMethods(a.add,null) );
        f( Reflect.compareMethods(null, a.add) );
        /*
            Comparison between a method and a closure :
            Not widely supported atm to justify officiel support
            var fadd : Dynamic = Reflect.field(a, "add");
            var fget : Dynamic = Reflect.field(a, "get");
            t( Reflect.compareMethods(fadd, fadd) );
            t( Reflect.compareMethods(a.add, fadd) );
            t( Reflect.compareMethods(fadd, a.add) );
            f( Reflect.compareMethods(fadd, fget) );
            f( Reflect.compareMethods(fadd, a.get) );
            f( Reflect.compareMethods(fadd, null) );
        */
    }
    

    Also, possible use case

    class Test {
        static function main() {
            var a = new A();
            var i:I = a;
            trace(Reflect.compareMethods(a.test, i.test)); //returns true
        }
    }
    
    interface I
    {
        function test():Void;
    }
    
    class A implements I
    {
        public function new() {}
        public function test() {}
    }