![](/img/trans.png)
[英]What is the best way to get Haxe function parameter types using a macro?
[英]Using local variables in function built with haxe macro
我有一个LangBuilder
宏类; 它用于构建langObjects:Map<String, Dynamic>
在编译时以各种语言langObjects:Map<String, Dynamic>
文本langObjects:Map<String, Dynamic>
,并通过@:build
宏在类中注入此结构。 地图的每个项目都包含支持的每种语言的字段。 结果是:
@:build(LangBuilder.build())
class Lang{}
trace(Lang.langObjects["hello-world"].en); //outputs "Hello World!"
trace(Lang.langObjects["hello-world"].it); //outputs "Ciao Mondo!"
这非常有效,但我想我可以使用函数getLangText
隐藏langObjects
结构,其中包含文本id(例如"hello-world"
)和语言代码(例如"it"
)的参数。
所以我试图将这个函数添加到类中:
public static function getLangText(id:String, lang:String)
其非宏版本可表示为:
public static function getLangText(id:String, lang:String){
var _langObj_id = langObjects[id];
switch(lang){
case "it":
return _langObj_id.it;
case "en":
return _langObj_id.en;
}
return "Missing Translation";
如果我使用此代码将此函数转换为宏:
var code = macro {
var _langObj_id = langObjects[$i{"id"}];
switch($i{"lang"}){
case "it":
return _langObj_id.it;
case "en":
return _langObj_id.en;
}
return "Missing translation";
};
var myFunc:Function = {
args: [{
name: "id",
type: TPath({name: "String", pack: []}),
meta: null
},
{
name: "lang",
type: TPath({name: "String", pack: []}),
meta: null
}],
ret: (macro:String),
expr: macro $code
};
fields.push({
pos: Context.currentPos(),
name: "getLangText",
meta: null,
kind: FieldType.FFun(myFunc),
doc: null,
access: [Access.APublic, Access.AStatic]
});
......它没有问题。 但是我想知道如何在没有switch
情况下编写它,使其更灵活,并学习一些关于haxe宏的东西。 我已经看到了一些示例,其中可以使用$p{}
或使用object.$fieldName
在宏中访问字段。 然而,haxe手册警告第二种形式只能用于简单的标识符; 例如object.${fieldName}
不起作用。
所以我试试这段代码:
var code = macro {
var l:String = $i{"lang"};
var _langObj_id = langObjects[$i{"id"}];
return _langObj_id.$l;
};
编译器出错
未知标识符:l
在包含return _langObj_id.$l;
。
然后我尝试使用$p{}
具体化:
var code = macro {
var _langObj_id = langObjects[$i{"id"}];
return macro $p{["_langObj_id", $i{"lang"}]};
};
但错误类似:
未知标识符:lang
我肯定可以将langObjects
结构更改为Map<String, Map<String, String>>
,然后将代码更改为:
var code = macro {
return macro langObjects[$i{"id"}][$i{"lang"}];
};
我认为这会有效,但现在我试图理解为什么_langObj_id.$lang
和$p{["_langObj_id", $i{"lang"}]}
都不起作用,以及正确的方法是什么在这种情况下访问一个字段。
在compile- / macro-time时不知道lang
参数的值,所以我看不出如何生成像langObjects["mytext"].en
这样的字段访问表达式。 在运行时,实际调用getLangText()
时, lang
可以是"en"
,或其他任何东西。 因此,仍然需要一个switch-case,if-else-chain或反射来处理所有可能的值。
如果不使用由构建宏创建的getLangText()
是表达式宏/ macro function
,则函数调用将在编译时进行求值,并替换为它返回的表达式。 这将允许您根据参数生成适当的字段访问表达式。 它可能看起来像这样:
class Macro {
public static var langObjects = ["mytext" => {en: "hello", de: "hallo"}];
public static macro function getLangText(id:String, lang:String) {
return macro {
var langObject = Macro.langObjects[$v{id}];
langObject.$lang;
}
}
}
class Main {
static function main() {
trace(Macro.getLangText("mytext", "en"));
trace(Macro.getLangText("mytext", "de"));
}
}
在JS目标上编译如下:
Main.main = function() {
var langObject = Macro.langObjects.get("mytext");
console.log("source/Main.hx:3:",langObject.en);
var langObject1 = Macro.langObjects.get("mytext");
console.log("source/Main.hx:4:",langObject1.de);
};
也许这就是你要找的东西? 很难说不知道你想要解决什么问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.