简体   繁体   English

在Haxe宏中的值数组上应用函数

[英]Apply a function on array of values inside Haxe macro

I generate an array of Int inside Haxe macro and would like to apply a function on it like this: 我在Haxe宏中生成一个Int数组,并想在其上应用一个函数,如下所示:

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();
    }
}

Usage: 用法:

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 compile-time I would like to do this in macro. 因为编译时一切都是已知的,所以我想在宏中执行此操作。

KevinResoL's answer is basically correct, except it seems you want distinct() to be executed at compile-time (as you can see in try.haxe's output tab, the generated JS code contains the thx.Arrays.distinct() call). KevinResoL的答案基本上是正确的,除了你似乎想要在编译时执行distinct() (正如你在try.haxe的输出选项卡中看到的那样,生成的JS代码包含thx.Arrays.distinct()调用)。

The easiest solution is probably to call distinct() right away in allOf() : 最简单的解决方案可能就是在allOf()allOf()调用distinct() 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() , since you're comparing expressions - by default it uses a simple equality check ( == ), which isn't good enough. 如您所见,您还需要为distinct()定义自定义predicate ,因为您正在比较表达式 - 默认情况下它使用简单的相等性检查( == ),这不够好。

The generated code looks like this (if the id_ variables are declared inline ): 生成的代码如下所示(如果id_变量是inline声明的):

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

.distinct() is only available when you have using thx.Arrays in the module calling the function. .distinct()仅在调用函数的模块中using thx.Arrays时可用。 When you generate the expression with macro, you cannot guarantee the callsite has the using in place. 使用宏生成表达式时,无法保证调用点具有using位置。 So you should use the 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 on try haxe: http://try-haxe.mrcdk.com/#9B5d6 另请参阅这个有关haxe的工作示例: http ://try-haxe.mrcdk.com/#9B5d6

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM