我想使用宏来检查函数是否返回特定的泛型类型,比如说Array
,所以如果函数返回Array<Dynamic>
,Array<String>
,甚至是通用Array<T>
。
所以我尝试使用Context.unify
Array<Dynamic>
。它适用于Array<String>
或Array<Dynamic>
但是当type参数为“generic”时失败,因为ComplexType Array<T>
不会转换为带Type not found: T
的Type(请参阅代码下面)。是否有任何可能的方法来实现我的目标?
package;
#if macro
import haxe.macro.Context;
using haxe.macro.ComplexTypeTools;
#end
#if !macro @:build(Macros.build()) #end
class Main
{
public function test<T>():Array<T>
{
return [];
}
}
class Macros
{
public static function build()
{
#if macro
var fields = Context.getBuildFields();
for(field in fields)
{
switch(field.kind)
{
case FFun(f):
// try to unify Array<String> with Array<Dynamic>
trace(Context.unify((macro:Array<String>).toType(), (macro:Array<Dynamic>).toType()));
// true
// try to unify Array<T> with Array<Dynamic>
trace(Context.unify(f.ret.toType(), (macro:Array<Dynamic>).toType()));
// Type not found: T
default:
}
}
return null;
#end
}
}
答案 0 :(得分:2)
因此,检查TPath不是最好的主意。
基于先前关于动态可分配给任何类型的假设,我们可以用Dynamic替换不可转换的类型参数(例如Array<T>
= Array<Dynamic>
)并尝试统一它。
static function toTypeExt(c:ComplexType):Null<haxe.macro.Type>
{
try {
return c.toType();
} catch (error:Error)
{
switch (c)
{
case TPath(p):
//deep copy of the TPath with all type parameters as Dynamic
var paramsCopy = [for (i in 0...p.params.length) TPType(macro:Dynamic)];
var pCopy:TypePath = {
name: p.name,
pack: p.pack,
sub: p.sub,
params: paramsCopy
}
var cCopy = TPath(pCopy);
//convert after
return cCopy.toType();
default:
}
}
return null;
}
在构建宏中使用 toTypeExt()而不是toType。
trace(Context.unify(toTypeExt(f.ret), (macro:Array<Dynamic>).toType()));
对我来说看起来更像是一种解决方法,但是关于ComplexTypeTools.toType有一个奇怪的事情 - 它会在使用方法类型参数失败时使用类类型参数成功。
统一无法工作,因为无法将带有类型参数的ComplexType转换为Type(在该上下文中)。但是,由于您正在与Array统一,因此可以安全地假设任何数组都将与它统一(因为任何类型都可以分配给Dynamic http://haxe.org/manual/types-dynamic.html)。
可能不是 pritiest 解决方案,但是简单的TPath检查就是这里的方法:
case FFun(f):
switch (f.ret) {
case TPath({ name: "Array", pack: [], params: _ }):
trace("Yay!");
default:
}