Applying a function on an array of values โ€‹โ€‹inside a Haxe macro

I am generating an array Int

inside a Haxe macro and would like to apply a function to it like this:

typedef ComponentIdArray = Array<Int>;

class MyMacros {
    // Each descendant of 'Component' has static member 'id_'
    // Convert array of classes to corresponding indices
    public static macro function classesToIndices(indexClasses:Array<ExprOf<Class<Component>>>) {
        var ixs = [for (indexClass in indexClasses) {macro $indexClass.id_ ;}];
        return macro $a{ixs};
    }

    public static macro function allOf(indexClasses:Array<ExprOf<Class<Component>>>) {
        var indices = macro Matcher.classesToIndices($a{indexClasses});
        // FIXME
        // FIXME 'distinct' is a function from thx.core -- DOES NOT WORK
        //var indices2 = macro ($a{indices}.distinct());
        return macro MyMacros.allOfIndices($indices);
    }


    public static function allOfIndices(indices:ComponentIdArray) {
        trace(indices);
        //... normal function
        // currently I call indices.distinct() here
        return indices.distinct();
    }
}

      

Using:

class C1 extends Component {} // C1.id_ will be set to 1
class C2 extends Component {} // C2.id_ will be set to 2
var r = MyMacros.allOf(C1, C2, C1); // should return [1,2]

      

Since everything is known at compile time, I would like to do it in a macro.

+3


source to share


2 answers


KevinResoL's answer is mostly correct, except that you want to be distinct()

executed at compile time (as you can see in the try.haxe output tab, the generated JS code contains the call thx.Arrays.distinct()

).

The simplest solution is probably to call immediately distinct()

in allOf()

:

using haxe.macro.ExprTools;

public static macro function allOf(indexClasses:Array<ExprOf<Class<Component>>>) {
    indexClasses = indexClasses.distinct(function(e1, e2) {
        return e1.toString() == e2.toString();
    });
    var indices = macro Matcher.classesToIndices($a{indexClasses});
    return macro MyMacros.allOfIndices($indices);
}

      



As you can see, you also need to define a custom predicate

for distinct()

as you are comparing expressions - the default is simple equality check ( ==

), which is not good enough.

The generated code looks like this (if id_

variables are declared inline

):

var r = MyMacros.allOfIndices([1, 2]);

      

+2


source


.distinct()

available only if present using thx.Arrays

in the module calling the function. When you create an expression using a macro, you cannot guarantee that callsite has using

. Therefore, you should use a static call instead:

This should work for your code:



public static macro function allOf(indexClasses:Array<ExprOf<Class<Component>>>) {
    var indices = macro Matcher.classesToIndices($a{indexClasses});
    var e = macro $a{indices}; // putting $a{} directly in function call will be reified as argument list, so we store the expression first
    return macro thx.Arrays.distinct($e);
}

      

Also see this working example at try haxe: http://try-haxe.mrcdk.com/#9B5d6

+1


source







All Articles