I generate an array of Int
inside Haxe macro and would like to apply a function on 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();
}
}
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).
The easiest solution is probably to call distinct()
right away 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()
, since you're comparing expressions - by default it uses a simple equality check ( ==
), which isn't good enough.
The generated code looks like this (if the id_
variables are declared inline
):
var r = MyMacros.allOfIndices([1, 2]);
.distinct()
is only available when you have using thx.Arrays
in the module calling the function. When you generate the expression with macro, you cannot guarantee the callsite has the using
in place. 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.