【发布时间】:2018-11-25 21:55:44
【问题描述】:
我有一个LangBuilder 宏类;它用于在编译时构建各种语言的文本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!"
这很好用,但我认为我可以使用带有文本 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{} reification:
var code = macro {
var _langObj_id = langObjects[$i{"id"}];
return macro $p{["_langObj_id", $i{"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"}]} 都不起作用,以及在这种情况下访问字段的正确方法是什么。
【问题讨论】: