COMMUNITY

How to use functions as keys


(Chrisvelevitch) #1

I’m trying to convert some AS3 code and target html5 and the code being converted uses functions as keys to a dictionary. I tried using DynamicAccess<Dynamic> in place of the Dictionary as follows:-

    private var myFunctionMap : DynamicAccess<Dynamic> = {};

    private function myFunction1() : Void {}
    private function myFunction2() : Void {}
    private function myFunction3() : Void {}

    private function main() : Void
    {
        myAdder(myFunction1);
        myAdder(myFunction2);
        myAdder(myFunction3);
        trace(myFunctionMap);
    }

    private function myAdder(key : Dynamic) : Void
    {
        if (!myFunctionMap.exists(key))
        {
            myFunctionMap.set(key, true);
        }
    }

When I run this, I only get one entry in myFunctionMap and the trace output is:-

{
	function(){ return f.method.apply(f.scope, arguments); } : true
}

It seems that myFunctionMap.exist(key) always returns true after the first function is set regardless of the actual function passed to it.

How do I use functions as keys? What is the alternative?


(Dan Korostelev) #2

You might want to rethink your approach and not use functions as keys, this looks really problematic.

DynamicAccess specifically only works with String keys, as it’s just an abstraction for anonymous object, the only reason it compiles in your example is because you basically turn off type checking by saying that key is Dynamic in your myAdder function.

I don’t think Haxe in its standard library has any data structure that can hold functions as keys, but you probably can invent something, or grab it from some haxelib or github repo. But I would strongly suggest reviewing the part of code to see if it’s possible to get rid of that. What are you after anyway? :slight_smile:


(Chrisvelevitch) #3

I’m trying to track, in a generic way, if the current function has called before and I tracking 500 distinct function calls cross many classes. The original AS3 code was using argument.callee but I had to hard-code the function reference when calling myAdder.


(Juraj Kirchheim) #4

On some platforms (including JS), you can get away with ObjectMap<Dynamic, Bool>: https://try.haxe.org/#Bd9D2

But if you switch target, expect exceptions :wink:


(Dan Korostelev) #5

I wonder if it would make sense to preprocess those functions with a macro instead and instrument them to call some logging function at their beginning, much like the code coverage instrumentation.