在 Haxe 宏中对值数组应用函数
Apply a function on array of values inside Haxe macro
我在 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();
}
}
用法:
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]
因为编译时一切都是已知的,所以我想在宏中这样做。
.distinct()
只有在调用该函数的模块中有 using thx.Arrays
时才可用。
当您使用宏生成表达式时,您不能保证调用站点具有 using
。所以你应该改用静态调用:
这应该适用于您的代码:
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);
}
另请参阅有关 try haxe 的工作示例:http://try-haxe.mrcdk.com/#9B5d6
KevinResoL 的回答基本上是正确的,除了你似乎希望 distinct()
在编译时执行(正如你在 try.haxe 的输出选项卡中看到的那样,生成的 JS 代码包含thx.Arrays.distinct()
呼唤)。
最简单的解决方案可能是在 allOf()
中立即调用 distinct()
:
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);
}
如您所见,您还需要为 distinct()
定义一个自定义 predicate
,因为您正在比较表达式 - 默认情况下它使用简单的相等性检查(==
),这还不够好。
生成的代码如下所示(如果声明 id_
变量 inline
):
var r = MyMacros.allOfIndices([1, 2]);
我在 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();
}
}
用法:
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]
因为编译时一切都是已知的,所以我想在宏中这样做。
.distinct()
只有在调用该函数的模块中有 using thx.Arrays
时才可用。
当您使用宏生成表达式时,您不能保证调用站点具有 using
。所以你应该改用静态调用:
这应该适用于您的代码:
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);
}
另请参阅有关 try haxe 的工作示例:http://try-haxe.mrcdk.com/#9B5d6
KevinResoL 的回答基本上是正确的,除了你似乎希望 distinct()
在编译时执行(正如你在 try.haxe 的输出选项卡中看到的那样,生成的 JS 代码包含thx.Arrays.distinct()
呼唤)。
最简单的解决方案可能是在 allOf()
中立即调用 distinct()
:
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);
}
如您所见,您还需要为 distinct()
定义一个自定义 predicate
,因为您正在比较表达式 - 默认情况下它使用简单的相等性检查(==
),这还不够好。
生成的代码如下所示(如果声明 id_
变量 inline
):
var r = MyMacros.allOfIndices([1, 2]);